1
1
from __future__ import annotations
2
2
3
- from collections .abc import Iterator
3
+ from collections .abc import Iterable , Iterator
4
4
from contextlib import contextmanager
5
5
from typing import Any , Callable , Final , TypeVar , cast
6
6
from typing_extensions import TypeAlias as _TypeAlias
@@ -414,6 +414,9 @@ def _is_subtype(self, left: Type, right: Type) -> bool:
414
414
return is_proper_subtype (left , right , subtype_context = self .subtype_context )
415
415
return is_subtype (left , right , subtype_context = self .subtype_context )
416
416
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
+
417
420
# visit_x(left) means: is left (which is an instance of X) a subtype of right?
418
421
419
422
def visit_unbound_type (self , left : UnboundType ) -> bool :
@@ -856,11 +859,25 @@ def variadic_tuple_subtype(self, left: TupleType, right: TupleType) -> bool:
856
859
# There are some items on the left that will never have a matching length
857
860
# on the right.
858
861
return False
862
+ left_prefix = left_unpack_index
863
+ left_suffix = len (left .items ) - left_prefix - 1
859
864
left_unpack = left .items [left_unpack_index ]
860
865
assert isinstance (left_unpack , UnpackType )
861
866
left_unpacked = get_proper_type (left_unpack .type )
862
867
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 )
864
881
return False
865
882
assert left_unpacked .type .fullname == "builtins.tuple"
866
883
left_item = left_unpacked .args [0 ]
@@ -871,8 +888,6 @@ def variadic_tuple_subtype(self, left: TupleType, right: TupleType) -> bool:
871
888
# and then check subtyping for all finite overlaps.
872
889
if not self ._is_subtype (left_item , right_item ):
873
890
return False
874
- left_prefix = left_unpack_index
875
- left_suffix = len (left .items ) - left_prefix - 1
876
891
max_overlap = max (0 , right_prefix - left_prefix , right_suffix - left_suffix )
877
892
for overlap in range (max_overlap + 1 ):
878
893
repr_items = left .items [:left_prefix ] + [left_item ] * overlap
@@ -883,6 +898,11 @@ def variadic_tuple_subtype(self, left: TupleType, right: TupleType) -> bool:
883
898
return False
884
899
return True
885
900
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
+
886
906
def visit_typeddict_type (self , left : TypedDictType ) -> bool :
887
907
right = self .right
888
908
if isinstance (right , Instance ):
@@ -1653,17 +1673,18 @@ def are_parameters_compatible(
1653
1673
return True
1654
1674
trivial_suffix = is_trivial_suffix (right ) and not is_proper_subtype
1655
1675
1676
+ trivial_vararg_suffix = False
1656
1677
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 )
1659
1680
and not is_proper_subtype
1681
+ and all (k .is_positional (star = True ) for k in left .arg_kinds )
1660
1682
):
1661
1683
# Similar to how (*Any, **Any) is considered a supertype of all callables, we consider
1662
1684
# (*Any) a supertype of all callables with positional arguments. This is needed in
1663
1685
# particular because we often refuse to try type inference if actual type is not
1664
1686
# 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
1667
1688
1668
1689
# Match up corresponding arguments and check them for compatibility. In
1669
1690
# 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
1697
1718
return not allow_partial_overlap and not trivial_suffix
1698
1719
return not is_compat (right_arg .typ , left_arg .typ )
1699
1720
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
+ ):
1701
1726
return False
1702
1727
1703
1728
# 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
1727
1752
# Phase 1c: Check var args. Right has an infinite series of optional positional
1728
1753
# arguments. Get all further positional args of left, and make sure
1729
1754
# 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 :
1732
1757
# Synthesize an anonymous formal argument for the right
1733
1758
right_by_position = right .try_synthesizing_arg_from_vararg (None )
1734
1759
assert right_by_position is not None
0 commit comments