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

CFE complains of reassigned final variable when it has not been reassigned #47991

Closed
mateusfccp opened this issue Dec 21, 2021 · 4 comments
Closed
Assignees
Labels
area-front-end Use area-front-end for front end / CFE / kernel format related issues. type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@mateusfccp
Copy link
Contributor

mateusfccp commented Dec 21, 2021

I am not sure, but it seems to be a regression in the CFE, as it started to happen after upgrading to the latest Flutter stable with Dart 2.15.

Consider the following code:

import 'dart:math';

void main() {
  () {
    final should = Random().nextBool() || Random().nextBool();
    final int a;

    if (should) {
      a = 1;
    } else {
      a = 2;
    }
  };
}

The following code does not compile. Instead, it generates the following errors:

line 9 - The final variable 'a' can only be set once. Try making 'a' non-final.
line 11 - The final variable 'a' can only be set once. Try making 'a' non-final.

Note that it requires this specific configuration:

  • If the code is not within a nested function, it won't happen. It doesn't need to be an anonymous function, however. A named nested function will also cause this behavior;
  • If the should variable has no || or &&, it won't happen. For example, final should = Random().nextBool(); won't cause this behavior;
  • If the boolean expression is passed directly to the if clause (if (Random().nextBool() || Random().nextBool())), it won't happen;
  • If final should = ... is moved to after final int a;, it won't happen.
@bwilkerson bwilkerson changed the title Analyzer complains of reassigned final variable when it has not been reassigned CFE complains of reassigned final variable when it has not been reassigned Dec 21, 2021
@lrhn lrhn added area-front-end Use area-front-end for front end / CFE / kernel format related issues. type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) labels Dec 21, 2021
@lrhn
Copy link
Member

lrhn commented Dec 21, 2021

Definitely weird behavior.

Seems like the boolean variable somehow interferes with the definite assignment analysis of the later variable.
If you move the final should = ... to after the final a; declaration, the error also goes away.

Boolean variables carrying data sounds like something @stereotype441 might know something about.

@stereotype441
Copy link
Member

Thanks for the bug report! I've reproduced the problem and I'll start investigating to see what's going wrong.

@stereotype441 stereotype441 self-assigned this Dec 23, 2021
@stereotype441
Copy link
Member

I've tracked down the problem to a subtle bug in flow analysis. See https://dart-review.googlesource.com/c/sdk/+/227361 for the fix, and a detailed description of what was going wrong.

@feinstein
Copy link

Excellent news!

copybara-service bot pushed a commit that referenced this issue Jan 11, 2022
This change adds assertions to ensure that the first phase of flow
analysis (calls to the AssignedVariables class) is complete before the
FlowAnalysis class is created.  It also calls AssignedVariables.finish
(which does additional assertions) from the FlowAnalysis constructor
(if the client hasn't done so already).

Adding these assersions exposed a few minor (but benign) bugs in the
usage of the flow analysis API.

- The flow analysis unit tests were failing to call
  AssignedVariables.declare.  This should have been caught by
  AssignedVariables.finish, but the flow analysis unit tests were
  failing to call that as well.

- Several flow analysis unit tests failed to declare the variables
  they were using (or in one case, the declaration was at the wrong
  location).

- In the CFE, DeclaredSourceConstructorBuilder.buildOutlineExpressions
  was failing to set up scopes properly when compiling a const
  constructor.

- In the CFE, SourceLoader.buildExpression was failing to call
  AssignedVariables.declare for variables in scope.

- In the CFE, the TypeInferrerImpl constructor was constructing the
  FlowAnalysis object eagerly, even though the AssignedVariables phase
  often hadn't completed yet.  I've fixed this by constructing
  FlowAnalysis lazily.

A follow-up CL will take advantage of the invariants checked by these
assertions to introduce the logic necessary to fix issue #47991.

Change-Id: Id680020dcd525632afa0820bc49c7b966b1ea534
Bug: #47991
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/227320
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-front-end Use area-front-end for front end / CFE / kernel format related issues. type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

4 participants