-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Summary
Due to a bug in the common front end, any implicit or explicit reference to this in an extension method is treated as equivalent to a local variable; accordingly it can undergo type promotion. The ability to type promote this is being removed for consistency with the specification and the behavior of the analyzer.
What is changing
Previously, any code inside an extension that did an is check on this would promote the type of this, so in the example below, lines (1) through (4) would be allowed (since class D defines property and method), but lines (5) through (8) would lead to compile-time errors (since class C does not):
class C {}
class D extends C {
int property;
void method() { ... }
}
extension on C {
void example() {
if (this is D) {
print(this.property); // (1)
print(property); // (2)
this.method(); // (3)
method(); // (4)
} else {
print(this.property); // (5)
print(property); // (6)
this.method(); // (7)
method(); // (8)
}
}
}However, the Dart analyzer (which also powers integration with editors such as IntelliJ and VSCode) did not allow this, so it considered lines (1) through (8) all to be compile-time errors.
We are changing the behavior of the front end to match the analyzer, so that lines (1) through (8) will all be compile-time errors.
Rationale
Making the analyzer and the common front end consistent should help reduce confusion, since code that is accepted by one tool won't be rejected by another. There are three reasons for going with the analyzer's behavior:
- The analyzer's behavior is more self-consistent (it disallows promotion of
thisboth in extensions and in classes). - The analyzer's behavior is consistent with the language specification (which specifies that only local variables and function parameters can undergo type promotion).
- Due to architectural constraints in the analyzer, changing its behavior to match that of the common front end would be a much larger undertaking, with greater risk of bugs.
Expected impact
We expect the impact to be extremely small for several reasons:
- Only a small fraction of Dart code exists inside extension method declarations; code inside class declarations is unaffected by this change.
- Any code that would be affected by this change would most likely be rendered erroneous by it, and since most users of Dart use the analyzer in some way or another (e.g. through an editor, or using a code generator), they would have already run into this problem and most likely worked around it by not trying to promote
this. - A trial run of the change through Google's internal source repository showed zero code broken by this change.
Mitigation
If you do have any code that is impacted by this change, you can always restore the old functionality by creating an explicit variable and initializing it to this, for example:
class C {}
class D extends C {
int property;
void method() { ... }
}
extension on C {
void example() {
var self = this;
if (self is D) { // Instead of `if (this is D)`
print(self.property); // Instead of `property` or `this.property`
self.method(); // Instead of `method()` or `this.method()`
}
}
}Additional information
- Inconsistent promotion of
thisin extension methods #44652: bug that will be fixed by this change - Type promotion for
thislanguage#1397: feature request to allowthisto be promoted by all tools, both in classes and in extensions.