Skip to content

Commit bf56d55

Browse files
authored
Merge branch 'master' into issue-18079
2 parents 4859d91 + 1ec3f44 commit bf56d55

File tree

3 files changed

+34
-28
lines changed

3 files changed

+34
-28
lines changed

mypy/subtypes.py

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -477,21 +477,17 @@ def visit_instance(self, left: Instance) -> bool:
477477
return self._is_subtype(left, unpacked)
478478
if left.type.has_base(right.partial_fallback.type.fullname):
479479
if not self.proper_subtype:
480-
# Special case to consider Foo[*tuple[Any, ...]] (i.e. bare Foo) a
481-
# subtype of Foo[<whatever>], when Foo is user defined variadic tuple type.
480+
# Special cases to consider:
481+
# * Plain tuple[Any, ...] instance is a subtype of all tuple types.
482+
# * Foo[*tuple[Any, ...]] (normalized) instance is a subtype of all
483+
# tuples with fallback to Foo (e.g. for variadic NamedTuples).
482484
mapped = map_instance_to_supertype(left, right.partial_fallback.type)
483-
for arg in map(get_proper_type, mapped.args):
484-
if isinstance(arg, UnpackType):
485-
unpacked = get_proper_type(arg.type)
486-
if not isinstance(unpacked, Instance):
487-
break
488-
assert unpacked.type.fullname == "builtins.tuple"
489-
if not isinstance(get_proper_type(unpacked.args[0]), AnyType):
490-
break
491-
elif not isinstance(arg, AnyType):
492-
break
493-
else:
494-
return True
485+
if is_erased_instance(mapped):
486+
if (
487+
mapped.type.fullname == "builtins.tuple"
488+
or mapped.type.has_type_var_tuple_type
489+
):
490+
return True
495491
return False
496492
if isinstance(right, TypeVarTupleType):
497493
# tuple[Any, ...] is like Any in the world of tuples (see special case above).
@@ -559,19 +555,8 @@ def visit_instance(self, left: Instance) -> bool:
559555
right_args = (
560556
right_prefix + (TupleType(list(right_middle), fallback),) + right_suffix
561557
)
562-
if not self.proper_subtype and t.args:
563-
for arg in map(get_proper_type, t.args):
564-
if isinstance(arg, UnpackType):
565-
unpacked = get_proper_type(arg.type)
566-
if not isinstance(unpacked, Instance):
567-
break
568-
assert unpacked.type.fullname == "builtins.tuple"
569-
if not isinstance(get_proper_type(unpacked.args[0]), AnyType):
570-
break
571-
elif not isinstance(arg, AnyType):
572-
break
573-
else:
574-
return True
558+
if not self.proper_subtype and is_erased_instance(t):
559+
return True
575560
if len(left_args) != len(right_args):
576561
return False
577562
type_params = zip(left_args, right_args, right.type.defn.type_vars)
@@ -2176,3 +2161,20 @@ def erase_return_self_types(typ: Type, self_type: Instance) -> Type:
21762161
]
21772162
)
21782163
return typ
2164+
2165+
2166+
def is_erased_instance(t: Instance) -> bool:
2167+
"""Is this an instance where all args are Any types?"""
2168+
if not t.args:
2169+
return False
2170+
for arg in t.args:
2171+
if isinstance(arg, UnpackType):
2172+
unpacked = get_proper_type(arg.type)
2173+
if not isinstance(unpacked, Instance):
2174+
return False
2175+
assert unpacked.type.fullname == "builtins.tuple"
2176+
if not isinstance(get_proper_type(unpacked.args[0]), AnyType):
2177+
return False
2178+
elif not isinstance(get_proper_type(arg), AnyType):
2179+
return False
2180+
return True

mypy/test/testsubtypes.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from mypy.subtypes import is_subtype
55
from mypy.test.helpers import Suite
66
from mypy.test.typefixture import InterfaceTypeFixture, TypeFixture
7-
from mypy.types import Instance, Type, UninhabitedType, UnpackType
7+
from mypy.types import Instance, TupleType, Type, UninhabitedType, UnpackType
88

99

1010
class SubtypingSuite(Suite):
@@ -274,6 +274,9 @@ def test_type_var_tuple_unpacked_variable_length_tuple(self) -> None:
274274
Instance(self.fx.gvi, [UnpackType(Instance(self.fx.std_tuplei, [self.fx.a]))]),
275275
)
276276

277+
def test_fallback_not_subtype_of_tuple(self) -> None:
278+
self.assert_not_subtype(self.fx.a, TupleType([self.fx.b], fallback=self.fx.a))
279+
277280
# IDEA: Maybe add these test cases (they are tested pretty well in type
278281
# checker tests already):
279282
# * more interface subtyping test cases

mypy_self_check.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[mypy]
22

33
strict = True
4+
strict_bytes = True
45
local_partial_types = True
56
disallow_any_unimported = True
67
show_traceback = True

0 commit comments

Comments
 (0)