55from contextlib import contextmanager
66
77from 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
99)
1010
1111from mypy .errors import Errors , report_internal_error
3030 Type , AnyType , CallableType , FunctionLike , Overloaded , TupleType , TypedDictType ,
3131 Instance , NoneTyp , strip_type , TypeType , TypeOfAny ,
3232 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
3434)
3535from mypy .sametypes import is_same_type , is_same_types
3636from mypy .messages import MessageBuilder , make_inferred_type_note
5555from mypy .join import join_types
5656from mypy .treetransform import TransformVisitor
5757from 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
5959from mypy .options import Options
6060from mypy .plugin import Plugin , CheckerPluginInterface
6161from mypy .sharedparse import BINARY_MAGIC_METHODS
@@ -495,12 +495,12 @@ def check_overlapping_overloads(self, defn: OverloadedFuncDef) -> None:
495495
496496 # Is the overload alternative's arguments subtypes of the implementation's?
497497 if not is_callable_compatible (impl , sig1 ,
498- is_compat = is_subtype ,
498+ is_compat = is_subtype_no_promote ,
499499 ignore_return = True ):
500500 self .msg .overloaded_signatures_arg_specific (i + 1 , defn .impl )
501501
502502 # 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 ):
504504 self .msg .overloaded_signatures_ret_specific (i + 1 , defn .impl )
505505
506506 # Here's the scoop about generators and coroutines.
@@ -3156,7 +3156,7 @@ def find_isinstance_check(self, node: Expression
31563156 else :
31573157 optional_type , comp_type = second_type , first_type
31583158 optional_expr = node .operands [1 ]
3159- if is_overlapping_types (optional_type , comp_type ):
3159+ if is_overlapping_erased_types (optional_type , comp_type ):
31603160 return {optional_expr : remove_optional (optional_type )}, {}
31613161 elif node .operators in [['in' ], ['not in' ]]:
31623162 expr = node .operands [0 ]
@@ -3167,7 +3167,7 @@ def find_isinstance_check(self, node: Expression
31673167 right_type .type .fullname () != 'builtins.object' ))
31683168 if (right_type and right_ok and is_optional (left_type ) and
31693169 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 )):
31713171 if node .operators == ['in' ]:
31723172 return {expr : remove_optional (left_type )}, {}
31733173 if node .operators == ['not in' ]:
@@ -3515,7 +3515,8 @@ def conditional_type_map(expr: Expression,
35153515 and is_proper_subtype (current_type , proposed_type )):
35163516 # Expression is always of one of the types in proposed_type_ranges
35173517 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 ):
35193520 # Expression is never of any type in proposed_type_ranges
35203521 return None , {}
35213522 else :
@@ -3731,9 +3732,9 @@ def are_argument_counts_overlapping(t: CallableType, s: CallableType) -> bool:
37313732
37323733def is_unsafe_overlapping_overload_signatures (signature : CallableType ,
37333734 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.
37353736
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
37373738 of the following are true:
37383739
37393740 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,
37423743 Assumes that 'signature' appears earlier in the list of overload
37433744 alternatives then 'other' and that their argument counts are overlapping.
37443745 """
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.
37463748 #
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.
37493758 #
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' .
37533762 #
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 ,
37633769 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 ]
37653838
37663839
37673840def overload_can_never_match (signature : CallableType , other : CallableType ) -> bool :
@@ -3787,69 +3860,6 @@ def overload_can_never_match(signature: CallableType, other: CallableType) -> bo
37873860 ignore_return = True )
37883861
37893862
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-
38533863def is_more_general_arg_prefix (t : FunctionLike , s : FunctionLike ) -> bool :
38543864 """Does t have wider arguments than s?"""
38553865 # 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:
38673877 return False
38683878
38693879
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-
38843880def is_same_arg_prefix (t : CallableType , s : CallableType ) -> bool :
38853881 return is_callable_compatible (t , s ,
38863882 is_compat = is_same_type ,
@@ -3889,21 +3885,6 @@ def is_same_arg_prefix(t: CallableType, s: CallableType) -> bool:
38893885 ignore_pos_arg_names = True )
38903886
38913887
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-
39073888def infer_operator_assignment_method (typ : Type , operator : str ) -> Tuple [bool , str ]:
39083889 """Determine if operator assignment on given value type is in-place, and the method name.
39093890
@@ -4045,3 +4026,11 @@ def is_static(func: Union[FuncBase, Decorator]) -> bool:
40454026 elif isinstance (func , FuncBase ):
40464027 return func .is_static
40474028 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