Skip to content

Inconsistent behavior of field promotion in irrefutable patterns. #3418

Open
@stereotype441

Description

@stereotype441

During the development of the patterns feature, we decided that refutable pattern matches should trigger type promotion of the scrutinee, but irrefutable pattern matches shouldn't. For example, this is allowed:

test(int? i) {
  switch (i) {
    case var x!:
      i.isEven; // OK; `i` was promoted to `int` by the pattern match.
  }
}

But this is a compile-time error:

test(int? i) {
  var (x!) = i;
  i.isEven; // ERROR; `i` must be null checked.
}

I just realized that when I implemented field promotion, I forgot to follow these rules. Currently, field promotion works both in refutable and irrefutable pattern matches. For example:

class C {
  final int? _i;
  C(this._i);
}

test(C c) {
  var (x!) = c._i;
  c._i.isEven; // OK; `c._i` was promoted to `int` by the pattern match.
}

If I had discovered this problem earlier, I would have just fixed it without raising a fuss. But since we've passed the branch cut deadline for 3.2, I wanted to get the language team's opinion about what to do. Should I:

  1. Try to fix the inconsistency ASAP (so that the last example above is a compile-time error) and cherry-pick the fix into 3.2? This option is the best from the standpoint of language consistency, but it carries some non-zero risk of endangering the stability of the Dart 3.2 release, which is less than a month away (November 15).
  2. Fix the inconsistency in Dart 3.3, as a breaking change? This option avoids any risk to the stability of Dart 3.2, but it has the disadvantage that Dart 3.2 could in principle break some user code. I could do some experiments in Google3 to try to estimate just how breaking this would be.
  3. Fix the inconsistency for Dart 3.3, as a language-versioned change? This option is even better from the standpoint of risk, since it ensures that user code will only be broken by the change when they change their language version. But it's more costly to implement, since it means that flow analysis will have to support both the new and old behaviors for a long time.
  4. Don't bother fixing the inconsistency at all. This option is both low risk and low effort, but it leaves us with a rather unfortunate inconsistency that we have to document somewhere.

Personally I lean towards either 1 or 4, but I'm curious what others think.

CC @dart-lang/language-team

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugThere is a mistake in the language specification or in an active documentfield-promotionIssues related to addressing the lack of field promotionflow-analysisDiscussions about possible future improvements to flow analysispatternsIssues related to pattern matching.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions