5
5
from contextlib import contextmanager
6
6
7
7
from typing import (
8
- Dict , Set , List , cast , Tuple , TypeVar , Union , Optional , NamedTuple , Iterator , Any
8
+ Dict , Set , List , cast , Tuple , TypeVar , Union , Optional , NamedTuple , Iterator , Iterable , Any
9
9
)
10
10
11
11
from mypy .errors import Errors , report_internal_error
30
30
Type , AnyType , CallableType , FunctionLike , Overloaded , TupleType , TypedDictType ,
31
31
Instance , NoneTyp , strip_type , TypeType , TypeOfAny ,
32
32
UnionType , TypeVarId , TypeVarType , PartialType , DeletedType , UninhabitedType , TypeVarDef ,
33
- true_only , false_only , function_type , is_named_instance , union_items ,
33
+ true_only , false_only , function_type , is_named_instance , union_items , TypeQuery
34
34
)
35
35
from mypy .sametypes import is_same_type , is_same_types
36
36
from mypy .messages import MessageBuilder , make_inferred_type_note
55
55
from mypy .join import join_types
56
56
from mypy .treetransform import TransformVisitor
57
57
from mypy .binder import ConditionalTypeBinder , get_declaration
58
- from mypy .meet import is_overlapping_types , is_partially_overlapping_types
58
+ from mypy .meet import is_overlapping_erased_types , is_overlapping_types
59
59
from mypy .options import Options
60
60
from mypy .plugin import Plugin , CheckerPluginInterface
61
61
from mypy .sharedparse import BINARY_MAGIC_METHODS
@@ -495,12 +495,12 @@ def check_overlapping_overloads(self, defn: OverloadedFuncDef) -> None:
495
495
496
496
# Is the overload alternative's arguments subtypes of the implementation's?
497
497
if not is_callable_compatible (impl , sig1 ,
498
- is_compat = is_subtype ,
498
+ is_compat = is_subtype_no_promote ,
499
499
ignore_return = True ):
500
500
self .msg .overloaded_signatures_arg_specific (i + 1 , defn .impl )
501
501
502
502
# Is the overload alternative's return type a subtype of the implementation's?
503
- if not is_subtype (sig1 .ret_type , impl .ret_type ):
503
+ if not is_subtype_no_promote (sig1 .ret_type , impl .ret_type ):
504
504
self .msg .overloaded_signatures_ret_specific (i + 1 , defn .impl )
505
505
506
506
# Here's the scoop about generators and coroutines.
@@ -3156,7 +3156,7 @@ def find_isinstance_check(self, node: Expression
3156
3156
else :
3157
3157
optional_type , comp_type = second_type , first_type
3158
3158
optional_expr = node .operands [1 ]
3159
- if is_overlapping_types (optional_type , comp_type ):
3159
+ if is_overlapping_erased_types (optional_type , comp_type ):
3160
3160
return {optional_expr : remove_optional (optional_type )}, {}
3161
3161
elif node .operators in [['in' ], ['not in' ]]:
3162
3162
expr = node .operands [0 ]
@@ -3167,7 +3167,7 @@ def find_isinstance_check(self, node: Expression
3167
3167
right_type .type .fullname () != 'builtins.object' ))
3168
3168
if (right_type and right_ok and is_optional (left_type ) and
3169
3169
literal (expr ) == LITERAL_TYPE and not is_literal_none (expr ) and
3170
- is_overlapping_types (left_type , right_type )):
3170
+ is_overlapping_erased_types (left_type , right_type )):
3171
3171
if node .operators == ['in' ]:
3172
3172
return {expr : remove_optional (left_type )}, {}
3173
3173
if node .operators == ['not in' ]:
@@ -3515,7 +3515,8 @@ def conditional_type_map(expr: Expression,
3515
3515
and is_proper_subtype (current_type , proposed_type )):
3516
3516
# Expression is always of one of the types in proposed_type_ranges
3517
3517
return {}, None
3518
- elif not is_overlapping_types (current_type , proposed_type ):
3518
+ elif not is_overlapping_types (current_type , proposed_type ,
3519
+ prohibit_none_typevar_overlap = True ):
3519
3520
# Expression is never of any type in proposed_type_ranges
3520
3521
return None , {}
3521
3522
else :
@@ -3731,9 +3732,9 @@ def are_argument_counts_overlapping(t: CallableType, s: CallableType) -> bool:
3731
3732
3732
3733
def is_unsafe_overlapping_overload_signatures (signature : CallableType ,
3733
3734
other : CallableType ) -> bool :
3734
- """Check if two overloaded function signatures may be unsafely overlapping.
3735
+ """Check if two overloaded signatures are unsafely overlapping or partially overlapping.
3735
3736
3736
- We consider two functions 's' and 't' to be unsafely overlapping both if
3737
+ We consider two functions 's' and 't' to be unsafely overlapping if both
3737
3738
of the following are true:
3738
3739
3739
3740
1. s's parameters are all more precise or partially overlapping with t's
@@ -3742,26 +3743,98 @@ def is_unsafe_overlapping_overload_signatures(signature: CallableType,
3742
3743
Assumes that 'signature' appears earlier in the list of overload
3743
3744
alternatives then 'other' and that their argument counts are overlapping.
3744
3745
"""
3745
- # TODO: Handle partially overlapping parameter types
3746
+ # Try detaching callables from the containing class so that all TypeVars
3747
+ # are treated as being free.
3746
3748
#
3747
- # For example, the signatures "f(x: Union[A, B]) -> int" and "f(x: Union[B, C]) -> str"
3748
- # is unsafe: the parameter types are partially overlapping.
3749
+ # This lets us identify cases where the two signatures use completely
3750
+ # incompatible types -- e.g. see the testOverloadingInferUnionReturnWithMixedTypevars
3751
+ # test case.
3752
+ signature = detach_callable (signature )
3753
+ other = detach_callable (other )
3754
+
3755
+ # Note: We repeat this check twice in both directions due to a slight
3756
+ # asymmetry in 'is_callable_compatible'. When checking for partial overlaps,
3757
+ # we attempt to unify 'signature' and 'other' both against each other.
3749
3758
#
3750
- # To fix this, we need to either modify meet.is_overlapping_types or add a new
3751
- # function and use "is_more_precise(...) or is_partially_overlapping(...)" for the is_compat
3752
- # checks .
3759
+ # If 'signature' cannot be unified with 'other', we end early. However,
3760
+ # if 'other' cannot be modified with 'signature', the function continues
3761
+ # using the older version of 'other' .
3753
3762
#
3754
- # (We already have a rudimentary implementation of 'is_partially_overlapping', but it only
3755
- # attempts to handle the obvious cases -- see its docstring for more info.)
3756
-
3757
- def is_more_precise_or_partially_overlapping (t : Type , s : Type ) -> bool :
3758
- return is_more_precise (t , s ) or is_partially_overlapping_types (t , s )
3759
-
3760
- return is_callable_compatible (signature , other ,
3761
- is_compat = is_more_precise_or_partially_overlapping ,
3762
- is_compat_return = lambda l , r : not is_subtype (l , r ),
3763
+ # This discrepancy is unfortunately difficult to get rid of, so we repeat the
3764
+ # checks twice in both directions for now.
3765
+ return (is_callable_compatible (signature , other ,
3766
+ is_compat = is_overlapping_types_no_promote ,
3767
+ is_compat_return = lambda l , r : not is_subtype_no_promote (l , r ),
3768
+ ignore_return = False ,
3763
3769
check_args_covariantly = True ,
3764
- allow_partial_overlap = True )
3770
+ allow_partial_overlap = True ) or
3771
+ is_callable_compatible (other , signature ,
3772
+ is_compat = is_overlapping_types_no_promote ,
3773
+ is_compat_return = lambda l , r : not is_subtype_no_promote (r , l ),
3774
+ ignore_return = False ,
3775
+ check_args_covariantly = False ,
3776
+ allow_partial_overlap = True ))
3777
+
3778
+
3779
+ def detach_callable (typ : CallableType ) -> CallableType :
3780
+ """Ensures that the callable's type variables are 'detached' and independent of the context.
3781
+
3782
+ A callable normally keeps track of the type variables it uses within its 'variables' field.
3783
+ However, if the callable is from a method and that method is using a class type variable,
3784
+ the callable will not keep track of that type variable since it belongs to the class.
3785
+
3786
+ This function will traverse the callable and find all used type vars and add them to the
3787
+ variables field if it isn't already present.
3788
+
3789
+ The caller can then unify on all type variables whether or not the callable is originally
3790
+ from a class or not."""
3791
+ type_list = typ .arg_types + [typ .ret_type ]
3792
+
3793
+ appear_map = {} # type: Dict[str, List[int]]
3794
+ for i , inner_type in enumerate (type_list ):
3795
+ typevars_available = inner_type .accept (TypeVarExtractor ())
3796
+ for var in typevars_available :
3797
+ if var .fullname not in appear_map :
3798
+ appear_map [var .fullname ] = []
3799
+ appear_map [var .fullname ].append (i )
3800
+
3801
+ used_type_var_names = set ()
3802
+ for var_name , appearances in appear_map .items ():
3803
+ used_type_var_names .add (var_name )
3804
+
3805
+ all_type_vars = typ .accept (TypeVarExtractor ())
3806
+ new_variables = []
3807
+ for var in set (all_type_vars ):
3808
+ if var .fullname not in used_type_var_names :
3809
+ continue
3810
+ new_variables .append (TypeVarDef (
3811
+ name = var .name ,
3812
+ fullname = var .fullname ,
3813
+ id = var .id ,
3814
+ values = var .values ,
3815
+ upper_bound = var .upper_bound ,
3816
+ variance = var .variance ,
3817
+ ))
3818
+ out = typ .copy_modified (
3819
+ variables = new_variables ,
3820
+ arg_types = type_list [:- 1 ],
3821
+ ret_type = type_list [- 1 ],
3822
+ )
3823
+ return out
3824
+
3825
+
3826
+ class TypeVarExtractor (TypeQuery [List [TypeVarType ]]):
3827
+ def __init__ (self ) -> None :
3828
+ super ().__init__ (self ._merge )
3829
+
3830
+ def _merge (self , iter : Iterable [List [TypeVarType ]]) -> List [TypeVarType ]:
3831
+ out = []
3832
+ for item in iter :
3833
+ out .extend (item )
3834
+ return out
3835
+
3836
+ def visit_type_var (self , t : TypeVarType ) -> List [TypeVarType ]:
3837
+ return [t ]
3765
3838
3766
3839
3767
3840
def overload_can_never_match (signature : CallableType , other : CallableType ) -> bool :
@@ -3787,69 +3860,6 @@ def overload_can_never_match(signature: CallableType, other: CallableType) -> bo
3787
3860
ignore_return = True )
3788
3861
3789
3862
3790
- def is_unsafe_overlapping_operator_signatures (signature : Type , other : Type ) -> bool :
3791
- """Check if two operator method signatures may be unsafely overlapping.
3792
-
3793
- Two signatures s and t are overlapping if both can be valid for the same
3794
- statically typed values and the return types are incompatible.
3795
-
3796
- Assume calls are first checked against 'signature', then against 'other'.
3797
- Thus if 'signature' is more general than 'other', there is no unsafe
3798
- overlapping.
3799
-
3800
- TODO: Clean up this function and make it not perform type erasure.
3801
-
3802
- Context: This function was previously used to make sure both overloaded
3803
- functions and operator methods were not unsafely overlapping.
3804
-
3805
- We changed the semantics for we should handle overloaded definitions,
3806
- but not operator functions. (We can't reuse the same semantics for both:
3807
- the overload semantics are too restrictive here).
3808
-
3809
- We should rewrite this method so that:
3810
-
3811
- 1. It uses many of the improvements made to overloads: in particular,
3812
- eliminating type erasure.
3813
-
3814
- 2. It contains just the logic necessary for operator methods.
3815
- """
3816
- if isinstance (signature , CallableType ):
3817
- if isinstance (other , CallableType ):
3818
- # TODO varargs
3819
- # TODO keyword args
3820
- # TODO erasure
3821
- # TODO allow to vary covariantly
3822
- # Check if the argument counts are overlapping.
3823
- min_args = max (signature .min_args , other .min_args )
3824
- max_args = min (len (signature .arg_types ), len (other .arg_types ))
3825
- if min_args > max_args :
3826
- # Argument counts are not overlapping.
3827
- return False
3828
- # Signatures are overlapping iff if they are overlapping for the
3829
- # smallest common argument count.
3830
- for i in range (min_args ):
3831
- t1 = signature .arg_types [i ]
3832
- t2 = other .arg_types [i ]
3833
- if not is_overlapping_types (t1 , t2 ):
3834
- return False
3835
- # All arguments types for the smallest common argument count are
3836
- # overlapping => the signature is overlapping. The overlapping is
3837
- # safe if the return types are identical.
3838
- if is_same_type (signature .ret_type , other .ret_type ):
3839
- return False
3840
- # If the first signature has more general argument types, the
3841
- # latter will never be called
3842
- if is_more_general_arg_prefix (signature , other ):
3843
- return False
3844
- # Special case: all args are subtypes, and returns are subtypes
3845
- if (all (is_proper_subtype (s , o )
3846
- for (s , o ) in zip (signature .arg_types , other .arg_types )) and
3847
- is_subtype (signature .ret_type , other .ret_type )):
3848
- return False
3849
- return not is_more_precise_signature (signature , other )
3850
- return True
3851
-
3852
-
3853
3863
def is_more_general_arg_prefix (t : FunctionLike , s : FunctionLike ) -> bool :
3854
3864
"""Does t have wider arguments than s?"""
3855
3865
# TODO should an overload with additional items be allowed to be more
@@ -3867,20 +3877,6 @@ def is_more_general_arg_prefix(t: FunctionLike, s: FunctionLike) -> bool:
3867
3877
return False
3868
3878
3869
3879
3870
- def is_equivalent_type_var_def (tv1 : TypeVarDef , tv2 : TypeVarDef ) -> bool :
3871
- """Are type variable definitions equivalent?
3872
-
3873
- Ignore ids, locations in source file and names.
3874
- """
3875
- return (
3876
- tv1 .variance == tv2 .variance
3877
- and is_same_types (tv1 .values , tv2 .values )
3878
- and ((tv1 .upper_bound is None and tv2 .upper_bound is None )
3879
- or (tv1 .upper_bound is not None
3880
- and tv2 .upper_bound is not None
3881
- and is_same_type (tv1 .upper_bound , tv2 .upper_bound ))))
3882
-
3883
-
3884
3880
def is_same_arg_prefix (t : CallableType , s : CallableType ) -> bool :
3885
3881
return is_callable_compatible (t , s ,
3886
3882
is_compat = is_same_type ,
@@ -3889,21 +3885,6 @@ def is_same_arg_prefix(t: CallableType, s: CallableType) -> bool:
3889
3885
ignore_pos_arg_names = True )
3890
3886
3891
3887
3892
- def is_more_precise_signature (t : CallableType , s : CallableType ) -> bool :
3893
- """Is t more precise than s?
3894
- A signature t is more precise than s if all argument types and the return
3895
- type of t are more precise than the corresponding types in s.
3896
- Assume that the argument kinds and names are compatible, and that the
3897
- argument counts are overlapping.
3898
- """
3899
- # TODO generic function types
3900
- # Only consider the common prefix of argument types.
3901
- for argt , args in zip (t .arg_types , s .arg_types ):
3902
- if not is_more_precise (argt , args ):
3903
- return False
3904
- return is_more_precise (t .ret_type , s .ret_type )
3905
-
3906
-
3907
3888
def infer_operator_assignment_method (typ : Type , operator : str ) -> Tuple [bool , str ]:
3908
3889
"""Determine if operator assignment on given value type is in-place, and the method name.
3909
3890
@@ -4045,3 +4026,11 @@ def is_static(func: Union[FuncBase, Decorator]) -> bool:
4045
4026
elif isinstance (func , FuncBase ):
4046
4027
return func .is_static
4047
4028
assert False , "Unexpected func type: {}" .format (type (func ))
4029
+
4030
+
4031
+ def is_subtype_no_promote (left : Type , right : Type ) -> bool :
4032
+ return is_subtype (left , right , ignore_promotions = True )
4033
+
4034
+
4035
+ def is_overlapping_types_no_promote (left : Type , right : Type ) -> bool :
4036
+ return is_overlapping_types (left , right , ignore_promotions = True )
0 commit comments