-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Exhaustiveness checking for match statements #12267
Conversation
This comment has been minimized.
This comment has been minimized.
mypy/checker.py
Outdated
|
||
def remove_capture_conflicts(self, type_map: TypeMap, inferred_types: Dict[Var, Type]) -> None: | ||
if type_map: | ||
for expr, typ in type_map.copy().items(): |
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.
I think list(.items())
is more idiomatic (and probably cheaper) python
mypy/subtypes.py
Outdated
@@ -1237,11 +1237,13 @@ def _is_proper_subtype(left: Type, right: Type, *, | |||
class ProperSubtypeVisitor(TypeVisitor[bool]): | |||
def __init__(self, right: Type, *, | |||
ignore_promotions: bool = False, | |||
ignore_last_known_value: bool = False, |
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.
Nobody ever passes True
here. Is this deadcode?
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.
Seems fine, but some minor tweaks.
Diff from mypy_primer, showing the effect of this PR on open source code: pylox (https://github.com/sco1/pylox)
- pylox/containers/base.py:62: error: Missing return statement [return]
- pylox/containers/array.py:163: error: Missing return statement [return]
- pylox/interpreter.py:230: error: Missing return statement [return]
- pylox/interpreter.py:258: error: Missing return statement [return]
|
This doesn't seem to work: from enum import Enum, auto
class E1(Enum):
a = auto()
b = auto()
class E2(Enum):
x = auto()
y = auto()
def f(x: tuple[E1, E2]) -> int:
match x:
case (E1.a, E2.x):
return 0
case (E1.a, E2.y):
return 1
case (E1.b, E2.x):
return 2
case (E1.b, E2.y):
return 3 output:
but it's probably too difficult to support... |
Yeah, this seems a bit too complex for now. Since enums are internally expanded into unions of literal types to support exhaustiveness checking, an N-tuple of enums with M items each could be expanded a union of |
Closes python#12010. Mypy can now detect if a match statement covers all the possible values. Example: ``` def f(x: int | str) -> int: match x: case str(): return 0 case int(): return 1 # Mypy knows that we can't reach here ``` Most of the work was done by @freundTech. I did various minor updates and changes to tests. This doesn't handle some cases properly, including these: 1. We don't recognize that `match [*args]` fully covers a list type 2. Fake intersections don't work quite right (some tests are skipped) 3. We assume enums don't have custom `__eq__` methods Co-authored-by: Adrian Freund <[email protected]>
Closes #12010.
Mypy can now detect if a match statement covers all the possible values.
Example:
Most of the work was done by @freundTech. I did various minor updates
and changes to tests.
This doesn't handle some cases properly, including these:
match [*args]
fully covers a list type__eq__
methods