Skip to content

Commit 45d3fb9

Browse files
committed
Fix checking of match sequence pattern with bounded type variable
1 parent 1f200dd commit 45d3fb9

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

mypy/checkpattern.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
TypedDictType,
4747
TypeOfAny,
4848
TypeVarTupleType,
49+
TypeVarType,
4950
UninhabitedType,
5051
UnionType,
5152
UnpackType,
@@ -342,13 +343,11 @@ def visit_sequence_pattern(self, o: SequencePattern) -> PatternType:
342343
new_inner_type = UninhabitedType()
343344
for typ in new_inner_types:
344345
new_inner_type = join_types(new_inner_type, typ)
345-
new_type = self.construct_sequence_child(current_type, new_inner_type)
346-
if is_subtype(new_type, current_type):
347-
new_type, _ = self.chk.conditional_types_with_intersection(
348-
current_type, [get_type_range(new_type)], o, default=current_type
349-
)
346+
if isinstance(current_type, TypeVarType):
347+
new_bound = self.narrow_sequence_child(current_type.upper_bound, new_inner_type, o)
348+
new_type = current_type.copy_modified(upper_bound=new_bound)
350349
else:
351-
new_type = current_type
350+
new_type = self.narrow_sequence_child(current_type, new_inner_type, o)
352351
return PatternType(new_type, rest_type, captures)
353352

354353
def get_sequence_type(self, t: Type, context: Context) -> Type | None:
@@ -447,6 +446,16 @@ def expand_starred_pattern_types(
447446

448447
return new_types
449448

449+
def narrow_sequence_child(self, outer_type: Type, inner_type: Type, ctx: Context) -> Type:
450+
new_type = self.construct_sequence_child(outer_type, inner_type)
451+
if is_subtype(new_type, outer_type):
452+
new_type, _ = self.chk.conditional_types_with_intersection(
453+
outer_type, [get_type_range(new_type)], ctx, default=outer_type
454+
)
455+
else:
456+
new_type = outer_type
457+
return new_type
458+
450459
def visit_starred_pattern(self, o: StarredPattern) -> PatternType:
451460
captures: dict[Expression, Type] = {}
452461
if o.capture is not None:

test-data/unit/check-python310.test

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2343,3 +2343,30 @@ def test(xs: Tuple[Unpack[Ts]]) -> None:
23432343
reveal_type(b3) # N: Revealed type is "builtins.list[builtins.object]"
23442344
reveal_type(c3) # N: Revealed type is "builtins.int"
23452345
[builtins fixtures/tuple.pyi]
2346+
2347+
[case testMatchSequencePatternTypeVarBoundNoCrash]
2348+
# This was crashing: https://github.com/python/mypy/issues/18089
2349+
from typing import TypeVar, Sequence, Any
2350+
2351+
T = TypeVar("T", bound=Sequence[Any])
2352+
2353+
def f(x: T) -> None:
2354+
match x:
2355+
case [_]:
2356+
pass
2357+
[builtins fixtures/tuple.pyi]
2358+
2359+
[case testMatchSequencePatternTypeVarBoundNarrows]
2360+
from typing import TypeVar, Sequence
2361+
2362+
T = TypeVar("T", bound=Sequence[int | str])
2363+
2364+
def accept_seq_int(x: Sequence[int]): ...
2365+
2366+
def f(x: T) -> None:
2367+
match x:
2368+
case [1, 2]:
2369+
accept_seq_int(x)
2370+
case _:
2371+
accept_seq_int(x) # E: Argument 1 to "accept_seq_int" has incompatible type "T"; expected "Sequence[int]"
2372+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)