diff --git a/mypy/subtypes.py b/mypy/subtypes.py index fdde1c24670e..c10d01bda89b 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -463,8 +463,12 @@ def visit_instance(self, left: Instance) -> bool: assert unpacked.type.fullname == "builtins.tuple" if isinstance(get_proper_type(unpacked.args[0]), AnyType): return not self.proper_subtype - # TODO: we need a special case similar to above to consider (something that maps to) - # tuple[Any, ...] a subtype of Tuple[]. + if ( + left.type.fullname == "builtins.tuple" + and len(left.args) == 1 + and isinstance(get_proper_type(left.args[0]), AnyType) + ): + return True return False if isinstance(right, TypeVarTupleType): # tuple[Any, ...] is like Any in the world of tuples (see special case above). diff --git a/test-data/unit/check-tuples.test b/test-data/unit/check-tuples.test index 0e7c81edc498..1fb80ca8a580 100644 --- a/test-data/unit/check-tuples.test +++ b/test-data/unit/check-tuples.test @@ -107,19 +107,148 @@ class A: pass class B(A): pass [builtins fixtures/tuple.pyi] -[case testSubtypingWithNamedTupleType] -from typing import Tuple -t1: Tuple[A, A] -t2: tuple - -if int(): - t1 = t2 # E: Incompatible types in assignment (expression has type "Tuple[Any, ...]", variable has type "Tuple[A, A]") -if int(): - t2 = t1 +[case testSubtypingWithTupleType] +from __future__ import annotations +from typing import Any, Tuple + +tuple_aa: tuple[A, A] +Tuple_aa: Tuple[A, A] + +tuple_obj: tuple[object, ...] +Tuple_obj: Tuple[object, ...] + +tuple_obj_one: tuple[object] +Tuple_obj_one: Tuple[object] + +tuple_obj_two: tuple[object, object] +Tuple_obj_two: Tuple[object, object] + +tuple_any_implicit: tuple +Tuple_any_implicit: Tuple + +tuple_any: tuple[Any, ...] +Tuple_any: Tuple[Any, ...] + +tuple_any_one: tuple[Any] +Tuple_any_one: Tuple[Any] + +tuple_any_two: tuple[Any, Any] +Tuple_any_two: Tuple[Any, Any] + +def takes_tuple_aa(t: tuple[A, A]): ... + +takes_tuple_aa(tuple_aa) +takes_tuple_aa(Tuple_aa) +takes_tuple_aa(tuple_obj) # E: Argument 1 to "takes_tuple_aa" has incompatible type "Tuple[object, ...]"; expected "Tuple[A, A]" +takes_tuple_aa(Tuple_obj) # E: Argument 1 to "takes_tuple_aa" has incompatible type "Tuple[object, ...]"; expected "Tuple[A, A]" +takes_tuple_aa(tuple_obj_one) # E: Argument 1 to "takes_tuple_aa" has incompatible type "Tuple[object]"; expected "Tuple[A, A]" +takes_tuple_aa(Tuple_obj_one) # E: Argument 1 to "takes_tuple_aa" has incompatible type "Tuple[object]"; expected "Tuple[A, A]" +takes_tuple_aa(tuple_obj_two) # E: Argument 1 to "takes_tuple_aa" has incompatible type "Tuple[object, object]"; expected "Tuple[A, A]" +takes_tuple_aa(Tuple_obj_two) # E: Argument 1 to "takes_tuple_aa" has incompatible type "Tuple[object, object]"; expected "Tuple[A, A]" +takes_tuple_aa(tuple_any_implicit) +takes_tuple_aa(Tuple_any_implicit) +takes_tuple_aa(tuple_any) +takes_tuple_aa(Tuple_any) +takes_tuple_aa(tuple_any_one) # E: Argument 1 to "takes_tuple_aa" has incompatible type "Tuple[Any]"; expected "Tuple[A, A]" +takes_tuple_aa(Tuple_any_one) # E: Argument 1 to "takes_tuple_aa" has incompatible type "Tuple[Any]"; expected "Tuple[A, A]" +takes_tuple_aa(tuple_any_two) +takes_tuple_aa(Tuple_any_two) + +def takes_tuple_any_implicit(t: tuple): ... + +takes_tuple_any_implicit(tuple_aa) +takes_tuple_any_implicit(Tuple_aa) +takes_tuple_any_implicit(tuple_obj) +takes_tuple_any_implicit(Tuple_obj) +takes_tuple_any_implicit(tuple_obj_one) +takes_tuple_any_implicit(Tuple_obj_one) +takes_tuple_any_implicit(tuple_obj_two) +takes_tuple_any_implicit(Tuple_obj_two) +takes_tuple_any_implicit(tuple_any_implicit) +takes_tuple_any_implicit(Tuple_any_implicit) +takes_tuple_any_implicit(tuple_any) +takes_tuple_any_implicit(Tuple_any) +takes_tuple_any_implicit(tuple_any_one) +takes_tuple_any_implicit(Tuple_any_one) +takes_tuple_any_implicit(tuple_any_two) +takes_tuple_any_implicit(Tuple_any_two) + +def takes_tuple_any_one(t: tuple[Any]): ... + +takes_tuple_any_one(tuple_aa) # E: Argument 1 to "takes_tuple_any_one" has incompatible type "Tuple[A, A]"; expected "Tuple[Any]" +takes_tuple_any_one(Tuple_aa) # E: Argument 1 to "takes_tuple_any_one" has incompatible type "Tuple[A, A]"; expected "Tuple[Any]" +takes_tuple_any_one(tuple_obj) # E: Argument 1 to "takes_tuple_any_one" has incompatible type "Tuple[object, ...]"; expected "Tuple[Any]" +takes_tuple_any_one(Tuple_obj) # E: Argument 1 to "takes_tuple_any_one" has incompatible type "Tuple[object, ...]"; expected "Tuple[Any]" +takes_tuple_any_one(tuple_obj_one) +takes_tuple_any_one(Tuple_obj_one) +takes_tuple_any_one(tuple_obj_two) # E: Argument 1 to "takes_tuple_any_one" has incompatible type "Tuple[object, object]"; expected "Tuple[Any]" +takes_tuple_any_one(Tuple_obj_two) # E: Argument 1 to "takes_tuple_any_one" has incompatible type "Tuple[object, object]"; expected "Tuple[Any]" +takes_tuple_any_one(tuple_any_implicit) +takes_tuple_any_one(Tuple_any_implicit) +takes_tuple_any_one(tuple_any) +takes_tuple_any_one(Tuple_any) +takes_tuple_any_one(tuple_any_one) +takes_tuple_any_one(Tuple_any_one) +takes_tuple_any_one(tuple_any_two) # E: Argument 1 to "takes_tuple_any_one" has incompatible type "Tuple[Any, Any]"; expected "Tuple[Any]" +takes_tuple_any_one(Tuple_any_two) # E: Argument 1 to "takes_tuple_any_one" has incompatible type "Tuple[Any, Any]"; expected "Tuple[Any]" class A: pass [builtins fixtures/tuple.pyi] +[case testSubtypingWithTupleTypeSubclass] +from __future__ import annotations +from typing import Any, Tuple + +class A: ... + +inst_tuple_aa: Tuple[A, A] + +class tuple_aa_subclass(Tuple[A, A]): ... +inst_tuple_aa_subclass: tuple_aa_subclass + +class tuple_any_subclass(Tuple[Any, ...]): ... +inst_tuple_any_subclass: tuple_any_subclass + +class tuple_any_one_subclass(Tuple[Any]): ... +inst_tuple_any_one_subclass: tuple_any_one_subclass + +class tuple_any_two_subclass(Tuple[Any, Any]): ... +inst_tuple_any_two_subclass: tuple_any_two_subclass + +class tuple_obj_subclass(Tuple[object, ...]): ... +inst_tuple_obj_subclass: tuple_obj_subclass + +class tuple_obj_one_subclass(Tuple[object]): ... +inst_tuple_obj_one_subclass: tuple_obj_one_subclass + +class tuple_obj_two_subclass(Tuple[object, object]): ... +inst_tuple_obj_two_subclass: tuple_obj_two_subclass + +def takes_tuple_aa(t: Tuple[A, A]): ... + +takes_tuple_aa(inst_tuple_aa) +takes_tuple_aa(inst_tuple_aa_subclass) +# This next one should maybe not be an error +takes_tuple_aa(inst_tuple_any_subclass) # E: Argument 1 to "takes_tuple_aa" has incompatible type "tuple_any_subclass"; expected "Tuple[A, A]" +takes_tuple_aa(inst_tuple_any_one_subclass) # E: Argument 1 to "takes_tuple_aa" has incompatible type "tuple_any_one_subclass"; expected "Tuple[A, A]" +takes_tuple_aa(inst_tuple_any_two_subclass) +takes_tuple_aa(inst_tuple_obj_subclass) # E: Argument 1 to "takes_tuple_aa" has incompatible type "tuple_obj_subclass"; expected "Tuple[A, A]" +takes_tuple_aa(inst_tuple_obj_one_subclass) # E: Argument 1 to "takes_tuple_aa" has incompatible type "tuple_obj_one_subclass"; expected "Tuple[A, A]" +takes_tuple_aa(inst_tuple_obj_two_subclass) # E: Argument 1 to "takes_tuple_aa" has incompatible type "tuple_obj_two_subclass"; expected "Tuple[A, A]" + +def takes_tuple_aa_subclass(t: tuple_aa_subclass): ... + +takes_tuple_aa_subclass(inst_tuple_aa) # E: Argument 1 to "takes_tuple_aa_subclass" has incompatible type "Tuple[A, A]"; expected "tuple_aa_subclass" +takes_tuple_aa_subclass(inst_tuple_aa_subclass) +takes_tuple_aa_subclass(inst_tuple_any_subclass) # E: Argument 1 to "takes_tuple_aa_subclass" has incompatible type "tuple_any_subclass"; expected "tuple_aa_subclass" +takes_tuple_aa_subclass(inst_tuple_any_one_subclass) # E: Argument 1 to "takes_tuple_aa_subclass" has incompatible type "tuple_any_one_subclass"; expected "tuple_aa_subclass" +takes_tuple_aa_subclass(inst_tuple_any_two_subclass) # E: Argument 1 to "takes_tuple_aa_subclass" has incompatible type "tuple_any_two_subclass"; expected "tuple_aa_subclass" +takes_tuple_aa_subclass(inst_tuple_obj_subclass) # E: Argument 1 to "takes_tuple_aa_subclass" has incompatible type "tuple_obj_subclass"; expected "tuple_aa_subclass" +takes_tuple_aa_subclass(inst_tuple_obj_one_subclass) # E: Argument 1 to "takes_tuple_aa_subclass" has incompatible type "tuple_obj_one_subclass"; expected "tuple_aa_subclass" +takes_tuple_aa_subclass(inst_tuple_obj_two_subclass) # E: Argument 1 to "takes_tuple_aa_subclass" has incompatible type "tuple_obj_two_subclass"; expected "tuple_aa_subclass" + +[builtins fixtures/tuple.pyi] + [case testTupleInitializationWithNone] # flags: --no-strict-optional from typing import Tuple @@ -1522,3 +1651,20 @@ class Bar(aaaaaaaaaa): # E: Name "aaaaaaaaaa" is not defined class FooBarTuple(Tuple[Foo, Bar]): ... [builtins fixtures/tuple.pyi] + + +[case testTupleOverloadZipAny] +from typing import Any, Iterable, Iterator, Tuple, TypeVar, overload + +T = TypeVar("T") + +@overload +def zip(__i: Iterable[T]) -> Iterator[Tuple[T]]: ... +@overload +def zip(*i: Iterable[Any]) -> Iterator[Tuple[Any, ...]]: ... +def zip(i): ... + +def g(t: Tuple): + reveal_type(zip(*t)) # N: Revealed type is "typing.Iterator[builtins.tuple[Any, ...]]" + reveal_type(zip(t)) # N: Revealed type is "typing.Iterator[Tuple[Any]]" +[builtins fixtures/tuple.pyi]