We experimented with a "cheese shield" approach:
- compute the scope(s) of a binding variable as a set of position
ranges: s0..e0, s1..e1, ...
- compute the maximal scope for each variable: min(s0, s1, ...) ..
max(e0, e1, ...)
- treat the gaps as implicitly shadowing fields of the same name with
an erroneous local
If implementing the flow scoping is hard, I would think implementing the
shielded flow scoping is harder. The reason is that, while we might
think that there is a "natural rectangular scope" for a binding, there
really isn't. So the shield gives you _two_ kinds of irregularly-scoped
things.
But, design decisions should put the user first. So the question is,
whether the users are served better by:
- having fragmented scopes, through which light can shine, or
- patching the holes so you cannot access the fields without
qualification, even though the corresponding binding variable is "out of
scope"
And, it was really not clear which was the lesser of evils here. There
was some concern raised that this seemed scarier than it really is
because it is "new and different", but not intrinsically bad.
On 5/6/2020 5:28 AM, Manoj Palat wrote:
Hi Brian, Gavin, all,
Referring to Tagir’s example in [1]
if (obj instanceof String str) {
System.out.println(str.toLowerCase()); // str refers to
pattern binding
} else {
System.out.println(str.toLowerCase()); // str refers to the field
}
which is mentioned as Swiss cheese issue in the replies to [1]
From our development efforts in ecj (Eclipse Compiler for Java) for
this feature:
"swiss cheese" is hard for implementation by compiler(atleast ecj) and
understanding by users alike. For conflicts *within a local scope*
tools and users can use a structural strategy to find the nearest
candidate declaration to which any name reference should resolve,
deferring to flow analysis only the question, whether that resolution
is legal. This is not true for fields, where no structural 'proximity'
applies.
For that reason we propose a compromise, whereby "swiss cheese" is
allowed for pattern variables, but disallowed for fields shining
through in the holes of the cheese. This can be achieved by
disallowing a pattern variable to shadow a field. This is a
significantly smaller cost than having to invent cascades of names for
a cascade of pattern variables (the original motivation for swiss
cheese – as in Gavin’s message[2]).
With this proposals users have a chance to find a declaration by
looking only up and out starting from the point of reference. For the
implementation in ecj this makes a huge difference, because admitting
swiss cheese involving fields would require us to abandon the strict
separation of compilation phases 'resolve' and 'flow analysis'. Since
this separation is one of the fundamental design principles in the ecj
compiler, a change would require a major re-architecting of the
compiler, draining resources from other, high priority tasks.
In summary, we don't object to using flow criteria to determine
whether or not a variable is in scope, we only object to flow criteria
to *select* between different same-named variables, that could be in
scope at the same location. As far as we can see, this situation is
specific to fields and hence a change specific to fields should avoid
the major complexity.
In a spec, one could optionally generalize in a way that a pattern
variable may never shadow any other variable (local or field) that is
in scope.
[1http://mail.openjdk.java.net/pipermail/amber-spec-experts/2019-November/001835.html
[2]
_https://mail.openjdk.java.net/pipermail/amber-spec-experts/2019-December/001837.html_
Regards,
Manoj
Eclipse Java Dev