11from __future__ import annotations
22
3- from collections .abc import Iterator
3+ from collections .abc import Iterable , Iterator
44from contextlib import contextmanager
55from typing import Any , Callable , Final , TypeVar , cast
66from typing_extensions import TypeAlias as _TypeAlias
@@ -414,6 +414,9 @@ def _is_subtype(self, left: Type, right: Type) -> bool:
414414 return is_proper_subtype (left , right , subtype_context = self .subtype_context )
415415 return is_subtype (left , right , subtype_context = self .subtype_context )
416416
417+ def _all_subtypes (self , lefts : Iterable [Type ], rights : Iterable [Type ]) -> bool :
418+ return all (self ._is_subtype (li , ri ) for (li , ri ) in zip (lefts , rights ))
419+
417420 # visit_x(left) means: is left (which is an instance of X) a subtype of right?
418421
419422 def visit_unbound_type (self , left : UnboundType ) -> bool :
@@ -856,11 +859,25 @@ def variadic_tuple_subtype(self, left: TupleType, right: TupleType) -> bool:
856859 # There are some items on the left that will never have a matching length
857860 # on the right.
858861 return False
862+ left_prefix = left_unpack_index
863+ left_suffix = len (left .items ) - left_prefix - 1
859864 left_unpack = left .items [left_unpack_index ]
860865 assert isinstance (left_unpack , UnpackType )
861866 left_unpacked = get_proper_type (left_unpack .type )
862867 if not isinstance (left_unpacked , Instance ):
863- # *Ts unpacks can't be split.
868+ # *Ts unpack can't be split, except if it is all mapped to Anys or objects.
869+ if self .is_top_type (right_item ):
870+ right_prefix_types , middle , right_suffix_types = split_with_prefix_and_suffix (
871+ tuple (right .items ), left_prefix , left_suffix
872+ )
873+ if not all (
874+ self .is_top_type (ri ) or isinstance (ri , UnpackType ) for ri in middle
875+ ):
876+ return False
877+ # Also check the tails match as well.
878+ return self ._all_subtypes (
879+ left .items [:left_prefix ], right_prefix_types
880+ ) and self ._all_subtypes (left .items [- left_suffix :], right_suffix_types )
864881 return False
865882 assert left_unpacked .type .fullname == "builtins.tuple"
866883 left_item = left_unpacked .args [0 ]
@@ -871,8 +888,6 @@ def variadic_tuple_subtype(self, left: TupleType, right: TupleType) -> bool:
871888 # and then check subtyping for all finite overlaps.
872889 if not self ._is_subtype (left_item , right_item ):
873890 return False
874- left_prefix = left_unpack_index
875- left_suffix = len (left .items ) - left_prefix - 1
876891 max_overlap = max (0 , right_prefix - left_prefix , right_suffix - left_suffix )
877892 for overlap in range (max_overlap + 1 ):
878893 repr_items = left .items [:left_prefix ] + [left_item ] * overlap
@@ -883,6 +898,11 @@ def variadic_tuple_subtype(self, left: TupleType, right: TupleType) -> bool:
883898 return False
884899 return True
885900
901+ def is_top_type (self , typ : Type ) -> bool :
902+ if not self .proper_subtype and isinstance (get_proper_type (typ ), AnyType ):
903+ return True
904+ return is_named_instance (typ , "builtins.object" )
905+
886906 def visit_typeddict_type (self , left : TypedDictType ) -> bool :
887907 right = self .right
888908 if isinstance (right , Instance ):
@@ -1653,17 +1673,18 @@ def are_parameters_compatible(
16531673 return True
16541674 trivial_suffix = is_trivial_suffix (right ) and not is_proper_subtype
16551675
1676+ trivial_vararg_suffix = False
16561677 if (
1657- right .arg_kinds == [ARG_STAR ]
1658- and isinstance (get_proper_type (right .arg_types [0 ]), AnyType )
1678+ right .arg_kinds [ - 1 :] == [ARG_STAR ]
1679+ and isinstance (get_proper_type (right .arg_types [- 1 ]), AnyType )
16591680 and not is_proper_subtype
1681+ and all (k .is_positional (star = True ) for k in left .arg_kinds )
16601682 ):
16611683 # Similar to how (*Any, **Any) is considered a supertype of all callables, we consider
16621684 # (*Any) a supertype of all callables with positional arguments. This is needed in
16631685 # particular because we often refuse to try type inference if actual type is not
16641686 # a subtype of erased template type.
1665- if all (k .is_positional () for k in left .arg_kinds ) and ignore_pos_arg_names :
1666- return True
1687+ trivial_vararg_suffix = True
16671688
16681689 # Match up corresponding arguments and check them for compatibility. In
16691690 # every pair (argL, argR) of corresponding arguments from L and R, argL must
@@ -1697,7 +1718,11 @@ def _incompatible(left_arg: FormalArgument | None, right_arg: FormalArgument | N
16971718 return not allow_partial_overlap and not trivial_suffix
16981719 return not is_compat (right_arg .typ , left_arg .typ )
16991720
1700- if _incompatible (left_star , right_star ) or _incompatible (left_star2 , right_star2 ):
1721+ if (
1722+ _incompatible (left_star , right_star )
1723+ and not trivial_vararg_suffix
1724+ or _incompatible (left_star2 , right_star2 )
1725+ ):
17011726 return False
17021727
17031728 # Phase 1b: Check non-star args: for every arg right can accept, left must
@@ -1727,8 +1752,8 @@ def _incompatible(left_arg: FormalArgument | None, right_arg: FormalArgument | N
17271752 # Phase 1c: Check var args. Right has an infinite series of optional positional
17281753 # arguments. Get all further positional args of left, and make sure
17291754 # they're more general than the corresponding member in right.
1730- # TODO: are we handling UnpackType correctly here?
1731- if right_star is not None :
1755+ # TODO: handle suffix in UnpackType (i.e. *args: *Tuple[Ts, X, Y]).
1756+ if right_star is not None and not trivial_vararg_suffix :
17321757 # Synthesize an anonymous formal argument for the right
17331758 right_by_position = right .try_synthesizing_arg_from_vararg (None )
17341759 assert right_by_position is not None
0 commit comments