[BUG]UndefinedObject(Object)>>error:

Nathanael Schärli n.schaerli at gmx.net
Thu Oct 16 10:23:31 UTC 2003


Hi

I agree with Roel. Shadowing of globals should *not* be allowed as a
conceptual mechanism (because it is confusing), but it should occur when
a new global is created with a name that already exists as a class var
name (e.g., when a new class is loaded). However, whenever such
shadowing occurs, the UI should warn the user in a similar way as it
warns the user whan a instance variable is shadowed by a temporary
variable. In addition, I think it would be good to have a way of
searching the system for shadowed globals in order to get rid of them.

Concretely, this would mean the following:

1) It is not possible to create a class with a class variable that
shadows a global. This is exactly the same as it is not possible to
create a temp var with the same name as an inst. var.

2) When there is a class Foo with a class var Bar, and I later load a
class Bar into my system, the new global Bar should be shadowed in the
class Foo and all its subclasses, *and* there should be a warning that
the new global Bar is shadowed. Again, this completely corresponds to
the scenario where a new instance variable is shadowed by existing
temporary variables and the system gives the user a warning that this
should be resolved.

I assume that everyone agrees on 1) and the fact that the programmer
should be warned whenever a new conflict between a global and a class
variable occurs. This means that the only question that needs to be
answered is what happens between the point in time when the conflict
occurs (i.e., when the UI warns the programmer) and the point in time
when the programmer actually resolved the conflict by choosing another
name for one of the things (usually the class variable). 

Here, I clearly think that the behavior suggested by Roel and described
in 2) is better than what we have now. Let me explain why:

A) Situation as it is now

(Scenario 1) 
Assume that we have a class Bar in our system and that we now load a new
package from Squeakmap that contains a class Foo with a class var Bar
and a subclass SubFoo and that both Foo and SubFoo refer to the class
var Bar. According to the current semantics, this means that the name
Bar in the class SubFoo references our class Bar and *not* the class
variable Bar defined by Foo! And since the developer of this package did
not know about our class Bar, this is clearly not what he intended and
therefore there is a great probability that the code breaks! 

Of course, it only breaks until the programmer fixed the conflict (and
because the system warns him, he will hopefully do this quite quickly),
but nevertheless, there is a time when the system does not do what it
should be doing. And this can be bad, especially if the package has a
'postscript' that gets executed right after loading and therefore the
user maybe does not even have a chance to resolve this conflict before a
method in SubFoo gets executed! As a consequence, there would be an
error on loading the package and the user would be confused.

(Scenario 2)
As a second scenario, assume that we have an image with the class Foo
that defines a class var Bar and a subclass SubFoo. Furthermore, assume
there are methods Foo>>returnBar and SubFoo>>returnBar2 that refer to
the class var Bar. Initially, we do not have a global Bar, and so there
is no conflict and everything works beautifully. 

Now, we load a package with a class Bar. With the current rules, this
now means that name Bar in SubFoo>>returnBar2 should refer to the global
Bar (because the current rule does not imply shadowing in subclasses).
However, this is not what happens because the method SubFoo>>returnBar2
contains a direct reference to the class var Bar in the literal frame!

As a consequence, we are in a state that is very confusing because the
fact that the method SubFoo>>returnBar2 was compiled before loading Bar
makes the compiled method have a smenatics that is different then the
semantics of the interpreted source code of that method!

Again, it is clear that this only occurs until the programmer fixed the
conflict, but it nevertheless is bad and may confuse people
unnecessarily!


B) Situation as pointed out in 2) [i.e., class vars shadow global vars
(also in subclasses)]

(Scenario 1)
The problem described above does not occur. When the user loads the new
package, the name Bar in Foo and SubFoo still refers to the class var.
This is obviously what the programmer of the package intended and
therefore the new code works from the first moment! (Important note:
This does not mean that the system should not tell the user about the
conflict and that the user should resolve the ambiguity)

(Scenario 2)
Also here, the problem described above does not occur. When we load the
class Bar, the semantics says that all the class vars shadow the
globals, and therefore, the references in Foo>>returnBar and
SubFoo>>returnBar2 must refer to the class var. And indeed, this is also
what they do when the compiled method is executed. Thus, we do not have
a semantic difference between the specification and the compiled method!


Well, as a consequence of this, I suggest that we change Squeak as
follows:

- We change the compiler so that the principle of locality also applies
to class vars vs. globals (and not only to inst vars vs. temps). This
means that within a class and a metaclass, all available class vars (no
matter whether they were defined in the class or a superclass) shadow
globals.
- We make sure that it is not possible to define a class var that
shadows a global.
- We make sure that the system warns about conflicts between class vars
and globals whenever a change in the system (e.g., filing in a class or
creating a global) causes shadowing between a class var and a global.
- We add a mechanism to scan the system for shadowing of globals or inst
vars.

What do you guys think? Is there anything I am missing?
Nathanael




> -----Original Message-----
> From: owner-kcp at iam.unibe.ch [mailto:owner-kcp at iam.unibe.ch] On Behalf

> Of Roel Wuyts
> Sent: Dienstag, 14. Oktober 2003 15:49
> To: The general-purpose Squeak developers list
> Cc: kcp at iam.unibe.ch
> Subject: Re: [BUG]UndefinedObject(Object)>>error:
> 
> 
> Stef asked urged me to look into this discussion. I am trying to 
> comply, but I really have not a lot of time, so I did not check the 
> start of this thread on the Squeak mailing list (just the ones on the 
> KCP mailing list).
> 
>  From these mails (and without really understanding who is proposing 
> exactly which scoping/visibility rules) I notice that two separate 
> discussions are being held at the same time: (1) what 
> scoping/visibility rules do we want? (2) what happens when the system 
> changes (due to editing or file-in or ...). Of course these issues are
> related, but I'd prefer to have them discussed a bit more cleanly for 
> my sake of understanding :-)
> 
> So who is supporting which scoping/visibility?
> Quickly thinking about it, it seems that I prefer the same mechanism 
> as it exists for instance variables/temporary variables, where
> the shared 
> variable is treated as the temporary variable (and the global 
> variables 
> are treated as instance variables). Why? Well, because a 
> class contains 
> instance variables and methods, and these methods can contain 
> temporary 
> variables. Similarly, the system contains global variables, and the 
> classes amongst those can contain shared variables.
> 
> So, regarding what happens when conflicts occur (because of name 
> clashes due to editing or filing-in): I'd do the same as for instance 
> variables/temporary variables. If a global variable changes to a name 
> used by a class variable, the class variable shadows until we try to 
> edit someplace where it is used. Otherwise we cannot shadow it to 
> start with. So, in short, shadowing is only used to resolve conflicts 
> as a result of changes, and not as a possible mechanism (I do believe 
> that this is important).
> 
> 
> On Monday, Oct 13, 2003, at 23:18 Europe/Zurich, Andreas Raab wrote:
> 
> >>> But we should try Really Hard (tm) to encourage you to fix those
> >>> conflicts at the earliest time possible.
> >>
> >> But you cannot because we are not in a closed world assumption.
> >
> > Of course you can! All that's required is to be explicit.
> For example:
> > 	Smalltalk at: #Global.
> > 	self class classPool at: #Global.
> > 	SomeSharedPool at: #Global.
> > are all very explicit (and admittedly very ugly ;) But
> that's totally
> > unrelated to any "closed world assumption". I would much rather use 
> > one of the above instead of having Symbol to refer to a
> font. And it
> > would give me
> > a real incentive for fixing the name conflict.
> >
> >> You cannot know which names are used.
> >
> > You don't have to (see below).
> >
> >>> You may be able to load that
> >>> package containing the shadowed global, but whether you should be 
> >>> allowed to interactively change it without resolving the
> conflict is
> >>> quite a  different matter (and really what I meant by
> "preventing it
> >>> at all costs").
> >>
> >> You lost me here :)
> >
> > Looks like it. What I was saying is that when someone
> starts to modify
> > a
> > method with a potentially shadowed global the person should
> be told in
> > No
> > Unclear Terms that this global is not what it looks like. I
> think that
> > this
> > would solve 90% of the interesting situations simply because if you 
> > expect some reference to be a global (rather than the shadowing 
> > object) probably
> > the first thing you'll do is to print or inspect it (this is what I 
> > did with
> > the example posted by Peter). If the system kicks in and 
> tells you that
> > there is some shadowing going on it means that you are immediately 
> > aware of the fact that things may not be what they seem.
> >
> > It's only if the system silently compiles stuff (because
> the compiler
> > can
> > figure it out) but the user's got no idea about the situation that 
> > things get ugly.
> >
> >>> And note that if we force you to fix the problem the
> first time you
> >>> may be introducing one of these confusions it means that
> your scope
> >>> is still unique - e.g., it is clear that all existing
> references go
> >>> to the shadowed variable and it is simple to just do a global 
> >>> rename.
> >>
> >> but a rename will not work because another package on this cool 
> >> squeakMap may break you later.
> >
> > Which is a) no better or worse than any other change to a
> package (do
> > you
> > expect packages to be unchangable?) and b) has a very small 
> > probability as we are talking about shadowed globals which mostly 
> > come from class variables
> > so you would have to both, make a subclass and use that 
> class var in
> > order
> > to be affected. Seems like a VERY reasonable tradeoff to me.
> >
> > Cheers,
> >   - Andreas
> >
> >
> >
> Roel Wuyts                                                    
>           
>    DeComp
> roel.wuyts at ulb.ac.be                               Université 
> Libre de
> Bruxelles
> http://homepages.ulb.ac.be/~rowuyts/                          
>           
> Belgique
> Board Member of the European Smalltalk User Group: www.esug.org
> 
> 



More information about the Squeak-dev mailing list