Skip to content

Migration tool doesn't recognize Never in flow control #44420

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

Closed
nex3 opened this issue Dec 7, 2020 · 3 comments
Closed

Migration tool doesn't recognize Never in flow control #44420

nex3 opened this issue Dec 7, 2020 · 3 comments
Labels
area-migration (deprecated) Deprecated: this label is no longer actively used (was: issues with the `dart migrate` tool). customer-dart-sass NNBD Issues related to NNBD Release 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

@nex3
Copy link
Member

nex3 commented Dec 7, 2020

The migration tool doesn't recognize the effect functions that return Never have on the control flow of a function. Consider the following unmigrated code:

Never bail() => throw "oh no";

int foo() {
  int a;
  if (a == null) bail();
  return a;
}

The migrator correctly tries to change int a to int? a but it also tries to change int foo() to int? foo(), which is unnecessary.

@nex3 nex3 added type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) customer-dart-sass NNBD Issues related to NNBD Release area-migration (deprecated) Deprecated: this label is no longer actively used (was: issues with the `dart migrate` tool). labels Dec 7, 2020
@eernstg
Copy link
Member

eernstg commented Dec 8, 2020

Note the discussion in dart-lang/language#1143 about soundness issues that arise because a certain location in code is considered to be unreachable. The point is that (as long as mixed-version programs and the associated unsound null checking execution mode exist) it is possible for an expression whose static type is non-nullable to evaluate to null. For instance, bail() could return null. You could also have used int a = bar(); where bar is a function in legacy code (not under migration) that has return type int, and it could return null.

There is no guarantee that these nulls will be detected immediately, because it would be too costly in terms of run-time performance to enforce checks in every situation where it could occur. So the static analysis relaxes the analysis slightly, in order to consider certain otherwise-unreachable locations reachable, and that might be the reason for this behavior.

@stereotype441
Copy link
Member

Note the discussion in dart-lang/language#1143 about soundness issues that arise because a certain location in code is considered to be unreachable. The point is that (as long as mixed-version programs and the associated unsound null checking execution mode exist) it is possible for an expression whose static type is non-nullable to evaluate to null. For instance, bail() could return null. You could also have used int a = bar(); where bar is a function in legacy code (not under migration) that has return type int, and it could return null.

Actually, the final resolution we chose for dart-lang/language#1143 addresses things slightly differently (see dart-lang/language#1143 (comment)). There are several parts to the solution we chose, but the part that's relevant here is that in unsound null checking mode, the compiler inserts an invisible throw right after evaluating an expression whose static type is Never. So even with unsound null checking, the user can rely on the fact that a call to a function with static type Never will never return, and so can flow analysis. Which means that this is a perfectly acceptable program:

Never bail() => throw "oh no";

int foo() {
  int? a;
  if (a == null) bail();
  return a;
}

And I think it's what the migration tool ought to output.

I think what actually happened here was just an oversight: when writing the EdgeBuilder phase of the migration tool, we forgot to implement the rule that expressions of type Never will never return 😃

@stereotype441 stereotype441 added the P2 A bug or feature request we're likely to work on label Dec 8, 2020
@stereotype441
Copy link
Member

As of 1c7fe71, the null safety migration tool has been removed from active development and retired. No further work on the tool is planned.

If you still need help, or you believe this issue has been closed in error, please feel free to reopen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-migration (deprecated) Deprecated: this label is no longer actively used (was: issues with the `dart migrate` tool). customer-dart-sass NNBD Issues related to NNBD Release 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

No branches or pull requests

3 participants