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

Wrong flow analysis after non-nulable type and ==null #60114

Open
sgrekhov opened this issue Feb 12, 2025 · 4 comments
Open

Wrong flow analysis after non-nulable type and ==null #60114

sgrekhov opened this issue Feb 12, 2025 · 4 comments
Assignees
Labels
fe-analyzer-shared-flow-analysis legacy-area-front-end Legacy: Use area-dart-model instead. P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@sgrekhov
Copy link
Contributor

The following code works well and produces no errors in both CFE and the analyzer.

main() {
  late int i;
  String s = "";
  if (s == null) {  // Warning: unnecessary_null_comparison
    i = 42;
  }
  i; // No error
}

But according to the flow analysis specification:

operator== If N is an expression of the form E1 == E2, where the static type of E1 is T1 and the static type of E2 is T2, then:
...

  • Otherwise, if equivalentToNull(T1) and T2 is non-nullable, or equivalentToNull(T2) and T1 is non-nullable, then:
    • Let true(N) = unreachable(after(E2)).
    • Let false(N) = after(E2).

According to the above, the body of if (s == null) ... is unreachable and therefore initialization of i occurs in a dead code. This leaves i definitely unassigned and therefore i; should be a compile-time error.

Probably this happens because s == null is not always false in an unsound mode, but there are no mentions of unsound mode in the flow analysis spec.

cc @johnniwinther

Dart SDK version: 3.8.0-73.0.dev (dev) (Thu Feb 6 20:02:31 2025 -0800) on "windows_x64"

@dart-github-bot
Copy link
Collaborator

Summary: Flow analysis incorrectly handles late variable assignment within an if (s == null) block where s is a non-nullable String. The analyzer doesn't flag the subsequent use of the late variable as an error, despite it potentially being unassigned.

@dart-github-bot dart-github-bot added legacy-area-front-end Legacy: Use area-dart-model instead. triage-automation See https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot. type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) labels Feb 12, 2025
@lrhn lrhn removed the triage-automation See https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot. label Feb 12, 2025
@sgrekhov
Copy link
Contributor Author

Seems that the below is one more demonstration of the same issue.

void test(int x) {
  late int i;
  x ?? (i = 42); // Warning: dead_null_aware_expression
  i; // Definitely unassigned, but no expected error
//^
// [analyzer] unspecified
// [cfe] unspecified
}

@stereotype441 stereotype441 added the P2 A bug or feature request we're likely to work on label Feb 25, 2025
@stereotype441
Copy link
Member

@sgrekhov

Sorry for the slow response; this got buried in my inbox.

Probably this happens because s == null is not always false in an unsound mode, but there are no mentions of unsound mode in the flow analysis spec.

You are exactly right, that's the reason why the body of if (s == null) ... isn't flagged as unreachable in your example. I'll update the spec to match the implementation, and include a comment explaining the rationale.

Note that now that support for unsound null safety has been completely removed (0060b0f), I intend to change this behavior to match what the spec currently says. But since we're past the Beta 2 cutoff for Dart 3.8, I won't be doing it until Dart 3.9 at the earliest. See dart-lang/language#3100.

@stereotype441
Copy link
Member

You are exactly right, that's the reason why the body of if (s == null) ... isn't flagged as unreachable in your example. I'll update the spec to match the implementation, and include a comment explaining the rationale.

Proposed spec change is here: dart-lang/language#4284

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fe-analyzer-shared-flow-analysis legacy-area-front-end Legacy: Use area-dart-model instead. P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants