Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flow analysis sometimes ignores destructuring assignment #52745

Closed
natebosch opened this issue Jun 20, 2023 · 3 comments
Closed

Flow analysis sometimes ignores destructuring assignment #52745

natebosch opened this issue Jun 20, 2023 · 3 comments
Assignees
Labels
area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. area-front-end Use area-front-end for front end / CFE / kernel format related issues. soundness

Comments

@natebosch
Copy link
Member

There is an unexpected error in the following:

void main() {
  late String s;
  () {
    (s,) = ('',);
  }();
  print(s);
  //    ^ The late local variable 's' is definitely unassigned at this point.
}

The equivalent without using records has no diagnostic:

void main() {
  late String s;
  () {
    s = '';
  }();
  print(s);
}

This error shows up from both the analyzer and when trying to compile.

@natebosch natebosch added the area-front-end Use area-front-end for front end / CFE / kernel format related issues. label Jun 20, 2023
@johnniwinther
Copy link
Member

cc @stereotype441

@stereotype441 stereotype441 added the area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. label Jun 21, 2023
@stereotype441 stereotype441 self-assigned this Jun 21, 2023
@stereotype441
Copy link
Member

Good find, @natebosch! I see the problem. The bug is in the first phase of flow analysis, where it "looks ahead" to see which variables are potentially assigned in each code block, so that it can properly demote variables and adjust its notion of definite assignment at the top of loops and in the presence of closures. Both the analyzer and the CFE are failing to call AssignedVariables.write when a variable is assigned inside a pattern assignment, so flow analysis is failing to see pattern assignments when "looking ahead".

In your example, correct code is rejected. It's also possible to create examples in which incorrect code is accepted, resulting in a soundness violation, e.g.:

int f(int? i) {
  if (i == null) return 0;
  int k = 0;
  // `i` is promoted to non-nullable `int` now
  for (int j = 0; j < 2; j++) {
    // `i` should be demoted at this point, because it's assigned later in the
    // loop, so this statement should be an error.
    k += i;
    // Now assign a nullable value to `i`.
    (i,) = (null,);
  }
  return k;
}

void main() {
  print(f(0));
}

I've prototyped a fix. I'll add test cases and send it out for review ASAP.

@stereotype441
Copy link
Member

Fix is out for review (https://dart-review.googlesource.com/c/sdk/+/310502). Since this is a soundness issue, once the fix lands I'll follow up with a cherry-pick request.

@stereotype441 stereotype441 changed the title Definite assignment analysis ignores destructuring assignment Flow analysis sometimes ignores destructuring assignment Jun 21, 2023
copybara-service bot pushed a commit that referenced this issue Jul 6, 2023
Prior to this change, the first phase of flow analysis, in which flow
analysis "looks ahead" to see which variables are potentially assigned
in each code block, was failing to properly account for variables that
are assigned by pattern assignment expressions. This "look ahead"
information is used by flow analysis to determine the effects of
nonlinear control flow (e.g. to figure out which variables to demote
at the top of a loop, or to figure out which variables are potentially
assigned inside a closure). As a result, it was possible to construct
correct code that would be rejected by the analyzer and compiler, as
well as incorrect code that would (unsoundly) be accepted.

The fix is to call `AssignedVariables.write` from the analyzer's
`FlowAnalysisVisitor`, and from the CFE's `BodyBuilder`, to let flow
analysis know about variable assignments that occur inside pattern
assignment expressions.

Fixes: #52767.

Bug: #52745
Change-Id: If470f44a5e6b3afb03c1976a9609d884e2d3009c
Cherry-pick: https://dart-review.googlesource.com/c/sdk/+/310502
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/310702
Reviewed-by: Johnni Winther <[email protected]>
Reviewed-by: Konstantin Shcheglov <[email protected]>
Commit-Queue: Paul Berry <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. area-front-end Use area-front-end for front end / CFE / kernel format related issues. soundness
Projects
None yet
Development

No branches or pull requests

3 participants