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

Incorrect unreachable case warning with nullable matched value type and list pattern #55543

Closed
munificent opened this issue Apr 22, 2024 · 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. cfe-dysfunctionalities Issues for the CFE not behaving as intended P2 A bug or feature request we're likely to work on soundness

Comments

@munificent
Copy link
Member

If I analyze:

main() {
  List<int>? maybeList;
  switch (maybeList) {
    case [var element]:
      print(element + 1);
    case var otherwise?:        // line 6
      print(otherwise.length);  // line 7
  }
}

I get:

warning • temp.dart:7:7 • Dead code. Try removing the code, or fixing the code before it so that it can be reached.
          • dead_code
   info • temp.dart:6:5 • This case is covered by the previous cases. Try removing the case clause, or restructuring
          the preceding patterns. • unreachable_switch_case

It apparently thinks that the preceding case's list pattern covers... everything? This is doubly wrong: The first case won't match null, nor will it match non-null lists of any length other than one.

It seems to have something to do with the matched value type being nullable. If I change it to:

main() {
  List<int> maybeList = [];
  switch (maybeList) {
    case [var element]:
      print(element + 1);
    case var otherwise:
      print(otherwise.length);
  }
}

Then there are no warnings.

@munificent munificent added 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. labels Apr 22, 2024
@johnniwinther johnniwinther added the cfe-dysfunctionalities Issues for the CFE not behaving as intended label Apr 23, 2024
@johnniwinther johnniwinther self-assigned this Apr 23, 2024
@pq pq added the P2 A bug or feature request we're likely to work on label Apr 23, 2024
@johnniwinther
Copy link
Member

@stereotype441 I think the problem is in the flow analysis. It seems like maybeList is promoted to Never? via the "unmatched" path through [var element].

@stereotype441
Copy link
Member

Good catch, @munificent! And yes, @johnniwinther, your analysis is correct. I dug through the code, and the problem occurs whenever the following are all true of a list pattern:

  • The matched value type is List<U>? for some U.
  • The element type of the list pattern is V, where U <: V (meaning the only way that the type check implied by the list pattern can fail is if the matched value is null).
  • The list pattern doesn't match all possible list lengths.

When this happens, flow analysis incorrectly uses the ifFalse control flow branch of the type test as the "unmatched" control flow path for the pattern. In other words, it fails to account for the possibility that the list pattern might fail to match due to the list having an incorrect length. As a result, it promotes the matched value type to Never? (which is equivalent to Null) in the "unmatched" control flow path.

I'll work on a fix ASAP.

@stereotype441
Copy link
Member

Fix is out for review: https://dart-review.googlesource.com/c/sdk/+/364942

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. cfe-dysfunctionalities Issues for the CFE not behaving as intended P2 A bug or feature request we're likely to work on soundness
Projects
None yet
Development

No branches or pull requests

4 participants