diff --git a/mypy/checkpattern.py b/mypy/checkpattern.py index be6a78a021ba..6661abcdbfec 100644 --- a/mypy/checkpattern.py +++ b/mypy/checkpattern.py @@ -665,6 +665,13 @@ def visit_class_pattern(self, o: ClassPattern) -> PatternType: # # Check keyword patterns # + narrowed_type_for_members = narrowed_type + proper_narrowed_type_for_members = get_proper_type(narrowed_type_for_members) + if isinstance(proper_narrowed_type_for_members, TupleType) and ( + proper_narrowed_type_for_members.partial_fallback.type.is_named_tuple + ): + narrowed_type_for_members = proper_narrowed_type_for_members.partial_fallback + can_match = True for keyword, pattern in keyword_pairs: key_type: Type | None = None @@ -672,7 +679,7 @@ def visit_class_pattern(self, o: ClassPattern) -> PatternType: if keyword is not None: key_type = analyze_member_access( keyword, - narrowed_type, + narrowed_type_for_members, pattern, is_lvalue=False, is_super=False, diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test index e2074d347428..8d3fd45a5de3 100644 --- a/test-data/unit/check-python310.test +++ b/test-data/unit/check-python310.test @@ -960,6 +960,24 @@ match m: reveal_type(m) # N: Revealed type is "__main__.A[builtins.int]" reveal_type(i) # N: Revealed type is "builtins.int" +[case testMatchClassPatternCaptureGenericNamedTupleAlreadyKnown] +# flags: --warn-unreachable +from typing import Generic, NamedTuple, TypeVar + +T = TypeVar("T") + +class A(NamedTuple, Generic[T]): + a: T + +def f(m: A[int]) -> int: + match m: + case A(a=i): + return i + case _: + return "oops" # E: Statement is unreachable +[builtins fixtures/tuple.pyi] +[typing fixtures/typing-namedtuple.pyi] + [case testMatchClassPatternCaptureFilledGenericTypeAlias] from typing import Generic, TypeVar diff --git a/test-data/unit/check-python312.test b/test-data/unit/check-python312.test index 122bf5df14e7..35dc81305a61 100644 --- a/test-data/unit/check-python312.test +++ b/test-data/unit/check-python312.test @@ -1676,6 +1676,22 @@ e: M[bool] # E: Value of type variable "T" of "M" cannot be "bool" [builtins fixtures/tuple.pyi] [typing fixtures/typing-full.pyi] +[case testMatchClassPatternCapturePEP695GenericNamedTupleAlreadyKnown] +# flags: --warn-unreachable +from typing import NamedTuple + +class N[T](NamedTuple): + x: T + +def f(n: N[int]) -> int: + match n: + case N(x=value): + return value + case _: + return "oops" # E: Statement is unreachable +[builtins fixtures/tuple.pyi] +[typing fixtures/typing-full.pyi] + [case testPEP695GenericTypedDict] from typing import TypedDict