From 2e5927f70545f63c3481e354e52aa31c76ff4033 Mon Sep 17 00:00:00 2001 From: EmmanuelNiyonshuti Date: Tue, 6 Oct 2026 11:30:29 +0200 Subject: [PATCH 1/2] Fix self type check for generic NamedTuple with constrained typevar --- mypy/checker.py | 5 ++++- test-data/unit/check-namedtuple.test | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mypy/checker.py b/mypy/checker.py index 9493a1014c3ee..affcedb790d54 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -105,7 +105,7 @@ def __init__(self) -> None: IterationErrorWatcher, report_internal_error, ) -from mypy.expandtype import expand_type +from mypy.expandtype import expand_type, expand_type_by_instance from mypy.literals import Key, extract_var_from_literal_hash, literal, literal_hash from mypy.maptype import map_instance_to_supertype from mypy.meet import is_overlapping_types, meet_types @@ -1778,6 +1778,9 @@ def require_correct_self_argument(self, func: Type, defn: FuncDef) -> bool: return True arg_type = func.arg_types[0] + p_arg = get_proper_type(arg_type) + if isinstance(ref_type, TupleType) and isinstance(p_arg, TupleType): + ref_type = expand_type_by_instance(ref_type, p_arg.partial_fallback) if defn.is_class or defn.name == "__new__": ref_type = mypy.types.TypeType.make_normalized(ref_type) if is_same_type(arg_type, ref_type): diff --git a/test-data/unit/check-namedtuple.test b/test-data/unit/check-namedtuple.test index 1ed57c72fcd23..b2e49a8bed2aa 100644 --- a/test-data/unit/check-namedtuple.test +++ b/test-data/unit/check-namedtuple.test @@ -1296,6 +1296,22 @@ reveal_type(foo(x, nts)) # N: Revealed type is "builtins.tuple[builtins.int | b [builtins fixtures/tuple.pyi] [typing fixtures/typing-namedtuple.pyi] +[case testGenericNamedTupleWithConstrainedTypeParams] +# https://github.com/python/mypy/issues/21453 + +from typing import Generic, NamedTuple, TypeVar + +S = TypeVar("S", str, bytes) + +class Result(NamedTuple, Generic[S]): + value: S + + def get_value(self) -> S: + reveal_type(self) # N: Revealed type is "tuple[builtins.str, fallback=__main__.Result[builtins.str]]" \ + # N: Revealed type is "tuple[builtins.bytes, fallback=__main__.Result[builtins.bytes]]" + return self.value +[builtins fixtures/tuple.pyi] + [case testGenericNamedTupleCallSyntax] from typing import NamedTuple, TypeVar From f7037aa6664a1ec226d27c0bc870c83e6b10bb48 Mon Sep 17 00:00:00 2001 From: EmmanuelNiyonshuti Date: Tue, 6 Oct 2026 11:50:02 +0200 Subject: [PATCH 2/2] expand ref_type --- mypy/checker.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mypy/checker.py b/mypy/checker.py index affcedb790d54..63851d34f8e1a 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1779,6 +1779,7 @@ def require_correct_self_argument(self, func: Type, defn: FuncDef) -> bool: arg_type = func.arg_types[0] p_arg = get_proper_type(arg_type) + ref_type = get_proper_type(ref_type) if isinstance(ref_type, TupleType) and isinstance(p_arg, TupleType): ref_type = expand_type_by_instance(ref_type, p_arg.partial_fallback) if defn.is_class or defn.name == "__new__":