-
Notifications
You must be signed in to change notification settings - Fork 213
Rework flow analysis of ==
and !=
.
#1134
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
Conversation
Previously, we specified flow states `null()` and `nonNull()` (similar to `true()` and `false()`), and the special behaviors of `== null` and `!= null` checks fell out of a general analysis of `E1 == E2`. But it didn't work in practice, because it required doing joins like `join(null(E1), null(E2))`, which isn't sound in general (because it carries the flow control implication that either E1 or E2 is evaluated but not both). Because of these problems, the implementation never matched this specification, and instead used ad-hoc pattern matching to recognize `== null` and `!= null`. In the new formulation, we remove the flow states `null()` and `nonNull()` and retain the ad-hoc pattern matching for `== null` and `!= null`, consistent with the current implementation. However, we also add cases to recognize when an equality test is guaranteed to evaluate to `true` or `false`; this addresses dart-lang/sdk#41985 and ensures that we recognize dead code associated with unnecessary null checks.
I will follow up with an implementation change that brings the implementation in line with these spec changes. A few small changes to the Flutter SDK will be necessary, to ignore dead code warnings that result from the fact that dead code analysis now detects unnecessary null checks. |
Implementation change: https://dart-review.googlesource.com/c/sdk/+/155926 |
Necessary Flutter changes are here: flutter/flutter#63007 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, for what it's worth. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, with a few comments. In particular, I think we have to use the notion of 'strictly non-nullable' for the analysis of ??
.
The new logic classifies the LHS and RHS of the equality check as either null, non-nullable, or potentially nullable, and then either promotes, treats the expression as equivalent to a boolean, or does nothing, as appropriate. This means, for example, that a comparison between a non-nullable value and `null` is now known to evaluate to `true` for reachability analysis. Note: as part of this change, it was tempting to trigger promotion whenever a varialbe is equality compared to an expression of type `Null`, but this would be unsound (consider `(int? x) => x == (x = null) ? true : x.isEven`). So we still only promote when the variable is compared to a literal `null`. Fixes #41985. There's a corresponding spec change out for review: dart-lang/language#1134 Change-Id: Id7f1d4eaa3b0fa57124445bb8352eef32c304feb Bug: #41985 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/155926 Reviewed-by: Konstantin Shcheglov <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
Previously, we specified flow states
null()
andnonNull()
(similarto
true()
andfalse()
), and the special behaviors of== null
and!= null
checks fell out of a general analysis ofE1 == E2
. But itdidn't work in practice, because it required doing joins like
join(null(E1), null(E2))
, which isn't sound in general (because itcarries the flow control implication that either E1 or E2 is evaluated
but not both). Because of these problems, the implementation never
matched this specification, and instead used ad-hoc pattern matching
to recognize
== null
and!= null
.In the new formulation, we remove the flow states
null()
andnonNull()
and retain the ad-hoc pattern matching for== null
and!= null
, consistent with the current implementation. However, wealso add cases to recognize when an equality test is guaranteed to
evaluate to
true
orfalse
; this addressesdart-lang/sdk#41985 and ensures that we
recognize dead code associated with unnecessary null checks.