Skip to content

Avoid false possibly-undefined errors after exhaustive match statements. - #22315

Open
nlsfnr wants to merge 2 commits into
python:masterfrom
nlsfnr:possibly-undefined-exhaustive-match
Open

nlsfnr wants to merge 2 commits into
python:masterfrom
nlsfnr:possibly-undefined-exhaustive-match

Conversation

@nlsfnr

@nlsfnr nlsfnr commented Oct 28, 2026 •

Copy link
Copy Markdown

fixes #13926 and #16992 (duplicates), i.e. false possibly-undefined errors after exhaustive match statements.

This PR applies the same approach as #20149, which did the same for if statements.

Adds a new attribute MatchStmt.is_exhaustive, which is set by the type checker when the remaining subject type is empty after the last case. This allows partially_defined.py to skip the implicit fall-through branch, which it already does for trailing catch-all cases.

@github-actions

Copy link
Copy Markdown
Contributor

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

@chrikrah chrikrah left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nlsfnr nothing blocks this from my side. Like #20149, a constrained TypeVar still reports: expand_typevars() checks copies, so the original MatchStmt keeps is_exhaustive=False.

# git archive fee4b07, Python 3.12, mypy 2.5.0+dev resolves into the export
$ python -m pytest -q -n 4 mypy/test/testcheck.py -k "PossiblyUndefined or Match"
264 passed, 1 skipped        # head fee4b07
$ python -m pytest -q mypy/test/testcheck.py -k testExhaustiveMatchNoFallThrough
1 failed        # partially_defined.py skip_branch() removed: lines 15, 23, 31 unexpectedly report
$ python -m mypy --no-incremental --enable-error-code possibly-undefined t.py
t.py:11: error: Name "y" may be undefined  [possibly-undefined]    # f(x: T): match, case int() / case str()
t.py:26: error: Name "y" may be undefined  [possibly-undefined]    # h(x: T): if isinstance int / elif str
# g(x: int | str), the same match as f: clean
# not run: mypyc build, self-check

non-blocking: a separate issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Detect exhaustiveness in partially-defined variable checks

2 participants

⌂ Proxy