diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 32b8d4d3bcd4..cf50159e4765 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -177,6 +177,8 @@ def visit_tuple_type(self, left: TupleType) -> bool: is_named_instance(right, 'typing.Reversible')): iter_type = right.args[0] return all(is_subtype(li, iter_type) for li in left.items) + if is_subtype(left.fallback, right, self.check_type_parameter): + return True return False elif isinstance(right, TupleType): if len(left.items) != len(right.items): diff --git a/test-data/unit/check-namedtuple.test b/test-data/unit/check-namedtuple.test index 82cebd1cb6d8..a234bf80e9ab 100644 --- a/test-data/unit/check-namedtuple.test +++ b/test-data/unit/check-namedtuple.test @@ -318,4 +318,24 @@ reveal_type(X._field_types) # E: Revealed type is 'builtins.dict[builtins.str, x = None # type: X reveal_type(x._field_types) # E: Revealed type is 'builtins.dict[builtins.str, Any]' -[builtins fixtures/dict.pyi] \ No newline at end of file +[builtins fixtures/dict.pyi] + +[case testNamedTupleAndOtherSuperclass] +from typing import NamedTuple + +class A: pass +def f(x: A) -> None: pass + +class B(NamedTuple('B', []), A): pass +f(B()) +x = None # type: A +x = B() + +# Sanity check: fail if baseclass does not match +class C: pass +def g(x: C) -> None: pass +class D(NamedTuple('D', []), A): pass + +g(D()) # E: Argument 1 to "g" has incompatible type "D"; expected "C" +y = None # type: C +y = D() # E: Incompatible types in assignment (expression has type "D", variable has type "C")