Skip to content

Commit 989729c

Browse files
Fix generic NamedTuple class pattern member lookup
1 parent 883b866 commit 989729c

File tree

3 files changed

+21
-13
lines changed

3 files changed

+21
-13
lines changed

mypy/checkpattern.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -665,14 +665,20 @@ def visit_class_pattern(self, o: ClassPattern) -> PatternType:
665665
#
666666
# Check keyword patterns
667667
#
668+
narrowed_type_for_members = narrowed_type
669+
if isinstance(narrowed_type_for_members, TupleType) and (
670+
narrowed_type_for_members.partial_fallback.type.is_named_tuple
671+
):
672+
narrowed_type_for_members = narrowed_type_for_members.partial_fallback
673+
668674
can_match = True
669675
for keyword, pattern in keyword_pairs:
670676
key_type: Type | None = None
671677
with self.msg.filter_errors() as local_errors:
672678
if keyword is not None:
673679
key_type = analyze_member_access(
674680
keyword,
675-
narrowed_type,
681+
narrowed_type_for_members,
676682
pattern,
677683
is_lvalue=False,
678684
is_super=False,
@@ -722,8 +728,6 @@ def get_class_pattern_type_ranges(self, typ: Type, o: ClassPattern) -> list[Type
722728

723729
if isinstance(p_typ, FunctionLike) and p_typ.is_type_obj():
724730
typ = fill_typevars_with_any(p_typ.type_object())
725-
if isinstance(typ, TupleType) and typ.partial_fallback.type.is_named_tuple:
726-
typ = typ.partial_fallback
727731
return [TypeRange(typ, is_upper_bound=False)]
728732
if (
729733
isinstance(o.class_ref.node, Var)

test-data/unit/check-python310.test

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -962,18 +962,20 @@ match m:
962962
reveal_type(i) # N: Revealed type is "builtins.int"
963963

964964
[case testMatchClassPatternCaptureGenericNamedTupleAlreadyKnown]
965+
# flags: --warn-unreachable
965966
from typing import Generic, NamedTuple, TypeVar
966967

967968
T = TypeVar("T")
968969

969970
class A(NamedTuple, Generic[T]):
970971
a: T
971972

972-
m: A[int]
973-
974-
match m:
975-
case A(a=i):
976-
reveal_type(i) # N: Revealed type is "builtins.int"
973+
def f(m: A[int]) -> int:
974+
match m:
975+
case A(a=i):
976+
return i
977+
case _:
978+
return "oops" # E: Statement is unreachable
977979
[builtins fixtures/tuple.pyi]
978980
[typing fixtures/typing-namedtuple.pyi]
979981

test-data/unit/check-python312.test

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,16 +1677,18 @@ e: M[bool] # E: Value of type variable "T" of "M" cannot be "bool"
16771677
[typing fixtures/typing-full.pyi]
16781678

16791679
[case testMatchClassPatternCapturePEP695GenericNamedTupleAlreadyKnown]
1680+
# flags: --warn-unreachable
16801681
from typing import NamedTuple
16811682

16821683
class N[T](NamedTuple):
16831684
x: T
16841685

1685-
n: N[int]
1686-
1687-
match n:
1688-
case N(x=value):
1689-
reveal_type(value) # N: Revealed type is "builtins.int"
1686+
def f(n: N[int]) -> int:
1687+
match n:
1688+
case N(x=value):
1689+
return value
1690+
case _:
1691+
return "oops" # E: Statement is unreachable
16901692
[builtins fixtures/tuple.pyi]
16911693
[typing fixtures/typing-full.pyi]
16921694

0 commit comments

Comments
 (0)