Skip to content

Flow analysis improperly demotes variables due to possible capture of a different instance of the variable #38791

@stereotype441

Description

@stereotype441

After https://dart-review.googlesource.com/c/sdk/+/120680 lands, flow analysis will only demote variables written to in closures if a closure exists that captures writes to the variable, so for example:

test(Object x) {
  if (x is int) {
    ...
    print(x + 1); // Ok, x is promoted
  }
  localFunction() {
    x = 'foo';
  }
  ...
  if (x is int) {
    ...
    print(x + 1); // Not ok; localFunction might have been called between the test and usage of x
  }
}

However, there is a corner case that is not yet handled properly:

test() {
  outerLocalFunction(Object x) {
    if (x is int) {
      ...
      print(x + 1); // Should be ok, but flow analysis thinks it isn't
    }
    innerLocalFunction() {
      x = 'foo';
    }
    ...
  }
  ...
}

What's happening in this second example is that innerLocalFunction captures a write to x. So on entry to outerLocalFunction, we assume that a closure for innerLocalFunction might exist (because outerLocalFunction might be called more than once), and therefore we prohibit promotion of x inside outerLocalFunction. But that's unnecessary, because if a closure for innerLocalFunction exists at the time that outerLocalFunction is entered, the writes to x that it captures are to a different instance of x.

I think this is fixable, but I'll want to think carefully through the solution to avoid unsoundness.

Metadata

Metadata

Assignees

Labels

NNBDIssues related to NNBD Releaselegacy-area-analyzerUse area-devexp instead.

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions