Skip to content

Promote local variables based on matching patterns when in record literals, tooΒ #4535

@eernstg

Description

@eernstg

Consider the following example:

void main() {
  Object x = 1;
  var y = true;
  final Object? z = 'Hello!';

  switch ((x, y, z)) {
    case (int(), true, String()):
      print('${x.isEven}, ${y && y}, ${z.length}');
    // Further cases, can be seen as a "matrix" of conditions.
    // case (..., ..., ...): ...
    // case (..., ..., ...): ...
    // case (..., ..., ...): ...
  }
}

This example has type errors (with the analyzer as well as the CFE, SDK 3.11.0-16.0.dev) because no promotion occurs for x even though the record pattern gives rise to a type query (using the object pattern int()). Similarly for z and String().

I think it would be useful if a promotion could be performed for the corresponding pair of a record component (like x) and the corresponding record component pattern (like int()), because this lets developers ask questions about several objects simultaneously, yielding a pattern match which is kind of matrix shaped.

The support for promoting a promotable local variable using this kind of correspondence is already available when it occurs alone:

void main() {
  Object x = 1;
  var y = true;
  final Object? z = 'Hello!';

  switch (x) {
    case int():
      switch (y) {
        case true:
          switch (z) {
            case String():
              print('${x.isEven}, ${y && y}, ${z.length}'); // OK!
          }
        case false: // No-op.
      }
  }
}

The nested approach does allow the variables to be promoted, but it is much more verbose than the "matrix" approach using record literals and record patterns.

The promotion of variables that occur as components of a record literal is a very narrow special case. A generalization that could work is nested records (so if ((1, (2, y))) case (_, (_, String())) {...} would promote y to String in the body). On the other hand, promoting variables that occur as elements in other non-atomic collection patterns (lists, maps) would probably not be very useful.

We have discussed this topic earlier, or at least some similar ideas, but apparently there is no issue on it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureProposed language feature that solves one or more problemspatternsIssues related to pattern matching.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions