Report error for irrefutable patterns that make remaining match patterns unreachable - #21926
Open
haeganm wants to merge 1 commit into
Open
Report error for irrefutable patterns that make remaining match patterns unreachable#21926haeganm wants to merge 1 commit into
haeganm wants to merge 1 commit into
Conversation
…rns unreachable CPython rejects a match statement at compile time when an unguarded irrefutable pattern (a capture or wildcard) appears in any case except the last one, and when an irrefutable alternative appears in a non-final position of an or pattern. mypy accepted both without any error, so a file that cannot even be imported checked clean. Add the check to semantic analysis, where every pattern is visited unconditionally, so it also fires in unchecked functions the same way the runtime SyntaxError does. Fixes python#21925
Contributor
|
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #21925
CPython rejects a match statement at compile time when an unguarded irrefutable pattern (a capture or wildcard) appears in any case except the last one:
It also rejects an irrefutable alternative in a non-final position of an or pattern (
case _ | 1:), wherever the or pattern appears, including nested inside sequence, mapping and class patterns. mypy reported nothing for either, so files that cannot even be imported checked clean.Two changes:
get_irrefutable_patterninpatterns.pyreturns the capture or wildcard pattern that makes a pattern irrefutable, following the compiler's definition: a capture, a wildcard, an as pattern whose subpattern is irrefutable, or an or pattern whose last alternative is irrefutable.visit_match_stmt) and for an irrefutable alternative in a non-final position of an or pattern (invisit_or_pattern). The check lives in semantic analysis rather than in the pattern checker because every pattern is visited there unconditionally, so it also fires in unchecked functions, matching the runtime SyntaxError. The error messages mirror CPython's, and the errors are reported withserious=Truelike the existing check forawaitoutside a coroutine.I verified the behavior against CPython 3.13 on a matrix of 26 cases (guarded and unguarded captures and wildcards, as patterns, or patterns in every position, and patterns nested in sequence, mapping and class patterns) by compiling each snippet with
compile()and comparing with mypy's verdict; they agree on all of them. The new test cases fail without this change and pass with it. Existing behavior is preserved: an irrefutable pattern in the last case, a guarded case, and refutable patterns that happen to match anything (likecase int():on anintsubject) still produce no error.