-
Notifications
You must be signed in to change notification settings - Fork 209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Do we bundle setters and getters? #520
Comments
Note that #504 contains further considerations about name clashes based on basenames, in the context of exports and imports. A conclusion from there could be to have something similar to the following rules: If a library L has a public declaration with basename Let D1 and D2 be two declarations re-exported by a library L by exports of distinct libraries L1 and L2. It is a compile-time error if D1 and D2 have the same name, unless they are the same declaration; it is a compile-time error D1 and D2 have the same basename, unless they are declared in the same library. If a library L has a top-level declaration with basename Let D1 and D2 be two declarations with basename We have to say these things slightly differently ('shadow' isn't well-defined, and L1 won't re-export that declaration when it's an error), but you get the gist. |
I think that bundling is a good and sound approach, and we should do it. We should also treat getter/setter declarations as one thing in all other settings (like the elsewhere mentioned shadowing of exports, and probably also whether a non-platform library import shadows a platform library import). |
I would be very happy to treat them uniformly in this way. We would need to understand carefully how breaking this would be. If all of the resulting changes are in places where our tools are already inconsistent, then I think it's completely reasonable to make the change in our preferred direction. Otherwise, we'll need to evaluate the breakage carefully. Perhaps a good start would be to get a set of co19 tests together that cover all of these cases, then evaluate the current behavior on those test cases? |
I wrote some extension method tests to verify that extension methods match at least the class semantics: https://dart-review.googlesource.com/c/sdk/+/112925 . |
The tests also include tests for the case that the local extension defines a setter (respectively getter) and another extension defines a getter (respectively setter) or method with the same base name. I'm assuming we want the same error there, but please validate (and see if there are more errors that we should be specifying now that I've missed). We should update the informal specification to make it clear that these are errors. |
The bundling for imports/exports was adopted into the language specification in #1161. |
The scope rules in Dart include a couple of elements which are specifically dealing with the names of getters and setters, but these rules do not seem to be a perfect fit for any underlying principles.
This issue is a proposal to say "yes", we do consider the names
id
andid=
to be related, we perform lexical lookups for both, and we insist that if we found one of them at a specific level then we must use the other one from the same level. For instance, if an instance getterid
is in scope and we haveid = e
then it must use an instance setterid=
, it cannot be a static setter nor a library setter.In particular, lookups for an identifier reference are specified in terms of the basenames of declarations (it was spelled out as
id
orid=
because that was written before the term basename was introduced):This means that
x + 1
below must fail, because there is no getter namedx
:This happens because d is the setter, and the only matching case is the one which proceeds to desugar
x
intothis.x
(statically and dynamically). If the setter is static then it matches a different case, but we get the same error.In any case, the underlying principle would be that a getter/setter pair is treated as a single entity (whose name is the basename and the name of the getter) and that entity is capable of shadowing other declarations with the same basename. And this is true even in the case where we only have a lone getter or a lone setter as the lexically nearest declaration.
However, unqualified function invocations do not get the same treatment (as stated here):
Note that this text has remained unchanged since 2013 when the language specification was added to the SDK repository, except that the declaration was named
$f_{id}$
.So the following must not fail, it will look up
x
the top-level method and ignore the instance setter:For an assignment
v = e
, we have the current text which is based on a lookup of the namev
and accepting the case where it is a variable, or the namev=
(which will be a setter); so this will allow a local getter to be ignored:An older version of this text (6d58ce9bfef) did bundle getters and setters for the dynamic semantics:
But the static analysis was not very specific:
That's all. This omits such cases as (1)
v
is not in the lexical scope (which would be the case whenv
is an inherited variable, and we should say that we proceed to check compile-time errors forthis.v = e
), (2) d is an instance getter, and there is no setter (at any level), etc.For consistency we should reintroduce the bundling of getters and setters also for assignments, preserving the broader coverage of cases that we have in the current text.
However, tools (as of 9dcd7267bacd0924e2bd17a8519e74d0ea480e94) disagree on this topic: With example 1,
dartanalyzer
reports no issues, butdart
reports that there is no getterx
. With example 2,dartanalyzer
reports no issues, butdart
reports that there is no methodx
. With example 3, bothdartanalyzer
anddart
report that there is no setterx
.We should decide on an underlying principle and then apply that principle consistently. This could be:
Every lookup for an identifier
id
finds the lexically nearest declaration with basenameid
, if any.This principle is consistent with the behavior that we currently see from the common front end (
dart
anddart2js
).It would introduce some new errors with the analyzer, and in that sense it would be a breaking change, but given that both
dart
anddart2js
are already reporting these errors we have previously considered such changes to be non-breaking "in practice".So, @lrhn, @leafpetersen, @munificent, WDYT?
The text was updated successfully, but these errors were encountered: