-
Notifications
You must be signed in to change notification settings - Fork 213
Consider expanding flow analysis' ability to prove that a pattern "always matches" #2980
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
Comments
After further experimentation, it appears that flow analysis can't even tell that |
I've got a fix out for review that addresses nearly all of the above: https://dart-review.googlesource.com/c/sdk/+/293860. I'll see if I can get it reviewed and landed before the beta cut. |
I think we can elaborate the rules a little, based on the matched value type. A pattern always matches a matched value type M, when it's:
The only real change is the NON_NULL for |
This fixes a minor bug in flow analysis which was preventing it from recognizing when a switch statement was trivially exhaustive, meaning one of its reachable cases was guaranteed to always match. This mostly addresses dart-lang/language#2980, but flow analysis still fails to recognize that: - A list pattern containing a just a single rest pattern always matches (unless the rest pattern has a subpattern that may fail to match). - A null check pattern always matches if its subpattern always matches and the matched value type is non-nullable. - The relational pattern `!= null` always matches if its subpattern always matches and the matched value type is non-nullable. Fortunately, these drawbacks are small and don't lead to unsoundness. I'll try to address them in follow up CLs. Bug: dart-lang/language#2980 Change-Id: Ie9f8564cde66a5a2c41114033ca3ff0e1a0f139a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/293860 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Paul Berry <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
…rivially exhaustive. If a list pattern consists of a single rest pattern, and that rest pattern is guaranteed to match, then the whole list pattern is guaranteed to match as well (provided that the matched value type is a subtype of the list pattern's required type). Bug: dart-lang/language#2980 Change-Id: I316cc93d4e696f094716be92e1fbc1cd3a43a73c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/294622 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Paul Berry <[email protected]>
…s) as trivially exhaustive. If a list pattern consists of a single rest pattern, and that rest pattern is guaranteed to match, then the whole list pattern is guaranteed to match as well (provided that the matched value type is a subtype of the list pattern's required type). Bug: dart-lang/language#2980 Change-Id: Ibdd3b2315676e763a0c44b6c0adf7ac528d349e3 Cherry-pick: https://dart-review.googlesource.com/c/sdk/+/294622 Fixes: #52018 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/294682 Reviewed-by: Konstantin Shcheglov <[email protected]>
This was fully implemented in time for the beta branch, except for two things:
The first of these was fixed and cherry-picked to the beta branch. The second is still outstanding. Since the feature now works as intended except for one bug, I'm going to close this issue and track the remaining work in dart-lang/sdk#52084. |
Today I spent some time writing some toy analysis code using patterns. I was building up a switch statement on an as-needed basis, so I had a
default
clause to handle the cases I hadn't written yet. The code looked like this:Then I got the bright idea that instead of a default clause, I ought to be able to use an object pattern, i.e.:
But this didn't work. The analyzer produced an error at (1): "The body might complete normally, causing 'null' to be returned, but the return type, 'CodeReference', is a potentially non-nullable type." But in truth, the switch statement is exhaustive (because the type of
element.enclosingElement
is non-nullable). Flow analysis just wasn't smart enough to see that it was.In the general case, it's not possible for flow analysis to be as smart as the exhaustiveness algorithm. This is a known limitation of the design of the compilation pipeline, and we have discussed it elsewhere (for example, dart-lang/sdk#51926 (comment)).
However, flow analysis does understand that variable and wildcard patterns might always match (because the type of the pattern is a supertype of the matched value type), and in those cases it considers the switch to be exhaustive. I think it would be worth expanding the set of patterns that flow analysis recognizes as "always matching" to include:
[...]
, if the required type is a supertype of the matched value typeThat would allow the example above to work. It would also reduce the number of situations where flow analysis and the exhaustiveness algorithm disagree about whether a switch is exhaustive, which should reduce user pain (see #2977).
(Note that if we were to implement this functionality prior to removing support for mixed-mode null safety, we would have to be careful to make sure that this didn't lead to unsoundness escalation (see #1143).
The text was updated successfully, but these errors were encountered: