@@ -1768,7 +1768,37 @@ def require_correct_self_argument(self, func: Type, defn: FuncDef) -> bool:
17681768 # This level of erasure matches the one in checkmember.check_self_arg(),
17691769 # better keep these two checks consistent.
17701770 erased = get_proper_type (erase_typevars (erase_to_bound (arg_type )))
1771- if not is_subtype (ref_type , erased , ignore_type_params = True ):
1771+
1772+ # Generic NamedTuple methods using constrained TypeVars can produce
1773+ # false positives here because constrained TypeVars are checked using
1774+ # union semantics during subtype comparison.
1775+ #
1776+ # Example:
1777+ # S = TypeVar("S", str, bytes)
1778+ #
1779+ # class Result(NamedTuple, Generic[S]):
1780+ # ...
1781+ #
1782+ # In this case:
1783+ # tuple[S] is compared against tuple[str]
1784+ #
1785+ # and incorrectly rejected.
1786+ #
1787+ # Skip this check for constrained generic NamedTuple tuple self types.
1788+ skip_namedtuple_constrained_check = (
1789+ isinstance (ref_type , TupleType )
1790+ and isinstance (arg_type , TupleType )
1791+ and ref_type .partial_fallback .type .tuple_type is not None
1792+ and any (
1793+ isinstance (item , TypeVarType ) and item .values
1794+ for item in ref_type .items
1795+ )
1796+ )
1797+
1798+ if (
1799+ not skip_namedtuple_constrained_check
1800+ and not is_subtype (ref_type , erased , ignore_type_params = True )
1801+ ):
17721802 if (
17731803 isinstance (erased , Instance )
17741804 and erased .type .is_protocol
0 commit comments