@@ -474,21 +474,17 @@ def visit_instance(self, left: Instance) -> bool:
474474 return self ._is_subtype (left , unpacked )
475475 if left .type .has_base (right .partial_fallback .type .fullname ):
476476 if not self .proper_subtype :
477- # Special case to consider Foo[*tuple[Any, ...]] (i.e. bare Foo) a
478- # subtype of Foo[<whatever>], when Foo is user defined variadic tuple type.
477+ # Special cases to consider:
478+ # * Plain tuple[Any, ...] instance is a subtype of all tuple types.
479+ # * Foo[*tuple[Any, ...]] (normalized) instance is a subtype of all
480+ # tuples with fallback to Foo (e.g. for variadic NamedTuples).
479481 mapped = map_instance_to_supertype (left , right .partial_fallback .type )
480- for arg in map (get_proper_type , mapped .args ):
481- if isinstance (arg , UnpackType ):
482- unpacked = get_proper_type (arg .type )
483- if not isinstance (unpacked , Instance ):
484- break
485- assert unpacked .type .fullname == "builtins.tuple"
486- if not isinstance (get_proper_type (unpacked .args [0 ]), AnyType ):
487- break
488- elif not isinstance (arg , AnyType ):
489- break
490- else :
491- return True
482+ if is_erased_instance (mapped ):
483+ if (
484+ mapped .type .fullname == "builtins.tuple"
485+ or mapped .type .has_type_var_tuple_type
486+ ):
487+ return True
492488 return False
493489 if isinstance (right , TypeVarTupleType ):
494490 # tuple[Any, ...] is like Any in the world of tuples (see special case above).
@@ -556,19 +552,8 @@ def visit_instance(self, left: Instance) -> bool:
556552 right_args = (
557553 right_prefix + (TupleType (list (right_middle ), fallback ),) + right_suffix
558554 )
559- if not self .proper_subtype and t .args :
560- for arg in map (get_proper_type , t .args ):
561- if isinstance (arg , UnpackType ):
562- unpacked = get_proper_type (arg .type )
563- if not isinstance (unpacked , Instance ):
564- break
565- assert unpacked .type .fullname == "builtins.tuple"
566- if not isinstance (get_proper_type (unpacked .args [0 ]), AnyType ):
567- break
568- elif not isinstance (arg , AnyType ):
569- break
570- else :
571- return True
555+ if not self .proper_subtype and is_erased_instance (t ):
556+ return True
572557 if len (left_args ) != len (right_args ):
573558 return False
574559 type_params = zip (left_args , right_args , right .type .defn .type_vars )
@@ -2151,3 +2136,21 @@ def erase_return_self_types(typ: Type, self_type: Instance) -> Type:
21512136 ]
21522137 )
21532138 return typ
2139+
2140+
2141+ def is_erased_instance (t : Instance ) -> bool :
2142+ """Is this an instance where all args are Any types?"""
2143+ if not t .args :
2144+ return False
2145+ for arg in map (get_proper_type , t .args ):
2146+ if isinstance (arg , UnpackType ):
2147+ unpacked = get_proper_type (arg .type )
2148+ if not isinstance (unpacked , Instance ):
2149+ return False
2150+ assert unpacked .type .fullname == "builtins.tuple"
2151+ if not isinstance (get_proper_type (unpacked .args [0 ]), AnyType ):
2152+ return False
2153+ elif not isinstance (arg , AnyType ):
2154+ return False
2155+ else :
2156+ return True
0 commit comments