-
-
Notifications
You must be signed in to change notification settings - Fork 3k
fix: Narrowing with "tags" on unions (of TypedDicts or normal classes) doesn't work with the match statement #18791
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
…) doesn't work with the match statement Signed-off-by: Gene Parmesan Thomas <201852096+gopoto@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
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.
This looks good, just had two minor comments
CHANGELOG.md
Outdated
|
|
||
| Contributed by Marc Mueller (PR [18641](https://github.com/python/mypy/pull/18641)) | ||
|
|
||
| ### Other Notable Fixes and Improvements |
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.
we typically will do changelog entries later, can you remove this?
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.
Removed the changelog entry for now; will add it later alongside other notes.
mypy/checker.py
Outdated
| pattern_map, else_map = conditional_types_to_typemaps( | ||
| named_subject, pattern_type.type, pattern_type.rest_type | ||
| ) | ||
| # Also refine the parent expression of the subject. |
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.
thanks for docs, but i think this is fairly clear from the propagate_up_typemap_info docstring, so could you remove the comment?
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.
Dropped the extra comment here since the helper’s docstring is enough
Signed-off-by: gopoto <201852096+gopoto@users.noreply.github.com>
6d03c52 to
0a6333a
Compare
|
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
Summary
Addressed issue #16286, which reported that
matchstatements failed to narrow unions when matching on discriminant values (e.g.tagfields inTypedDicts or classes). This led to mypy complaining about missing keys/attributes insidecaseblocks even though plainif ... ==branches worked.What changed?
mypy/checker.py:visit_match_stmt, after callingconditional_types_to_typemapsfor the subject, the resulting type map is passed throughpropagate_up_typemap_info(just like in theif/isinstancecode paths). This means if the subject is an attribute or index expression (d.tag/d["tag"]), we try to refine the parentdbased on the pattern.pattern_mapwhen it's defined, to avoidUnboundLocalErrorin unreachable branches.test-data/unit/check-python310.test:testMatchNarrowingUnionTypedDictViaIndexchecks thatmatch d["tag"]refines aTypedDictunion and allows access to the appropriate key in each branch.testMatchNarrowingUnionClassViaAttributechecks the same for a class union usingmatch d.tag.Why?
Previously, the binder only narrowed the type of the expression being matched (e.g.
d["tag"]), not the parent expression. Without propagating that information upwards, mypy didn't realize it could rule out unrelatedTypedDict/class variants in eachcase, leading to erroneoustypeddict-itemandunion-attrerrors. The fix mirrors the existing behaviour forifand similar checks.How was it tested?
pytest -k testMatchNarrowingUnionTypedDictViaIndexandpytest -k testMatchNarrowingUnionClassViaAttributeto confirm the new tests passed.pytest -k check-python310to ensure the entire pattern-matching suite still passes after the change.python runtests.py self).pre-commit run --all-filesto satisfy formatting and lint hooks.Checklist
CHANGELOG.md.Fixes #16286.
This PR was generated by an AI system in collaboration with maintainers: @hauntsaninja