Skip to content

Commit 176b052

Browse files
authored
Fix crash in match statement with unmatchable ClassPattern (#13731)
Fixes #12886 `contract_starred_pattern_types` and `expand_starred_pattern_types` are sort of like inverses of each other, so you get crashes if `contracted_inner_types` and `contracted_new_inner_types` don't correspond (in the case that `can_match` gets set to `False`). I'm not sure `can_match` is doing anything useful, so this PR now just gets rid of it.
1 parent 6a4c2c8 commit 176b052

File tree

2 files changed

+19
-9
lines changed

2 files changed

+19
-9
lines changed

mypy/checkpattern.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -257,16 +257,13 @@ def visit_sequence_pattern(self, o: SequencePattern) -> PatternType:
257257
contracted_inner_types = self.contract_starred_pattern_types(
258258
inner_types, star_position, required_patterns
259259
)
260-
can_match = True
261260
for p, t in zip(o.patterns, contracted_inner_types):
262261
pattern_type = self.accept(p, t)
263262
typ, rest, type_map = pattern_type
264-
if is_uninhabited(typ):
265-
can_match = False
266-
else:
267-
contracted_new_inner_types.append(typ)
268-
contracted_rest_inner_types.append(rest)
263+
contracted_new_inner_types.append(typ)
264+
contracted_rest_inner_types.append(rest)
269265
self.update_type_map(captures, type_map)
266+
270267
new_inner_types = self.expand_starred_pattern_types(
271268
contracted_new_inner_types, star_position, len(inner_types)
272269
)
@@ -279,9 +276,7 @@ def visit_sequence_pattern(self, o: SequencePattern) -> PatternType:
279276
#
280277
new_type: Type
281278
rest_type: Type = current_type
282-
if not can_match:
283-
new_type = UninhabitedType()
284-
elif isinstance(current_type, TupleType):
279+
if isinstance(current_type, TupleType):
285280
narrowed_inner_types = []
286281
inner_rest_types = []
287282
for inner_type, new_inner_type in zip(inner_types, new_inner_types):

test-data/unit/check-python310.test

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,21 @@ match x:
317317
case [str()]:
318318
pass
319319

320+
[case testMatchSequencePatternWithInvalidClassPattern]
321+
class Example:
322+
__match_args__ = ("value",)
323+
def __init__(self, value: str) -> None:
324+
self.value = value
325+
326+
SubClass: type[Example]
327+
328+
match [SubClass("a"), SubClass("b")]:
329+
case [SubClass(value), *rest]: # E: Expected type in class pattern; found "Type[__main__.Example]"
330+
reveal_type(value) # E: Cannot determine type of "value" \
331+
# N: Revealed type is "Any"
332+
reveal_type(rest) # N: Revealed type is "builtins.list[__main__.Example]"
333+
[builtins fixtures/tuple.pyi]
334+
320335
[case testMatchSequenceUnion-skip]
321336
from typing import List, Union
322337
m: Union[List[List[str]], str]

0 commit comments

Comments
 (0)