[Breaking Change] Disallow type promotion of `this` in extensions

90 views
Skip to first unread message

Franklin Yow

unread,
Jan 13, 2021, 4:41:37 PM1/13/21
to anno...@dartlang.org
We are proposing to make a minor breaking change to the behavior of `this` in extension methods.  This change is expected to be very low impact and will bring the common front end into alignment with both the analyzer and the Dart language specification.  A breaking change request has been filed.  Please share any feedback or concerns about this change on the referenced issue, or via any other of our usual forums.  For convenience, I include the text of the breaking change request below.

Thanks,
Paul

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 this both 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

  • #44652: bug that will be fixed by this change
  • dart-lang/language#1397: feature request to allow this to be promoted by all tools, both in classes and in extensions.


Franklin Yow | Program Manager | CoreDev Multiplatform | fran...@google.com | 206-531-1401

Paul Berry

unread,
Jan 15, 2021, 4:11:28 PM1/15/21
to anno...@dartlang.org

--
For more ways to connect visit https://dart.dev/community
---
To unsubscribe from this group and stop receiving emails from it, send an email to announce+u...@dartlang.org.
Reply all
Reply to author
Forward
0 new messages