@@ -1575,12 +1575,9 @@ def union_overload_matches(self, types: Sequence[Type]) -> Union[AnyType, Callab
15751575 def erased_signature_similarity (self , arg_types : List [Type ], arg_kinds : List [int ],
15761576 arg_names : Optional [Sequence [Optional [str ]]],
15771577 callee : CallableType ,
1578- context : Context ) -> int :
1579- """Determine whether arguments could match the signature at runtime.
1580-
1581- Return similarity level (0 = no match, 1 = can match, 2 = non-promotion match). See
1582- overload_arg_similarity for a discussion of similarity levels.
1583- """
1578+ context : Context ) -> bool :
1579+ """Determine whether arguments could match the signature at runtime, after
1580+ erasing types."""
15841581 formal_to_actual = map_actuals_to_formals (arg_kinds ,
15851582 arg_names ,
15861583 callee .arg_kinds ,
@@ -1590,55 +1587,22 @@ def erased_signature_similarity(self, arg_types: List[Type], arg_kinds: List[int
15901587 if not self .check_argument_count (callee , arg_types , arg_kinds , arg_names ,
15911588 formal_to_actual , None , None ):
15921589 # Too few or many arguments -> no match.
1593- return 0
1594-
1595- similarity = 2
1590+ return False
15961591
15971592 def check_arg (caller_type : Type , original_caller_type : Type , caller_kind : int ,
15981593 callee_type : Type , n : int , m : int , callee : CallableType ,
15991594 context : Context , messages : MessageBuilder ) -> None :
1600- nonlocal similarity
1601- similarity = min (similarity ,
1602- overload_arg_similarity (caller_type , callee_type ))
1603- if similarity == 0 :
1595+ if not arg_approximate_similarity (caller_type , callee_type ):
16041596 # No match -- exit early since none of the remaining work can change
16051597 # the result.
16061598 raise Finished
16071599
16081600 try :
16091601 self .check_argument_types (arg_types , arg_kinds , callee , formal_to_actual ,
16101602 context = context , check_arg = check_arg )
1603+ return True
16111604 except Finished :
1612- pass
1613-
1614- return similarity
1615-
1616- def match_signature_types (self , arg_types : List [Type ], arg_kinds : List [int ],
1617- arg_names : Optional [Sequence [Optional [str ]]], callee : CallableType ,
1618- context : Context ) -> bool :
1619- """Determine whether arguments types match the signature.
1620-
1621- Assume that argument counts are compatible.
1622-
1623- Return True if arguments match.
1624- """
1625- formal_to_actual = map_actuals_to_formals (arg_kinds ,
1626- arg_names ,
1627- callee .arg_kinds ,
1628- callee .arg_names ,
1629- lambda i : arg_types [i ])
1630- ok = True
1631-
1632- def check_arg (caller_type : Type , original_caller_type : Type , caller_kind : int ,
1633- callee_type : Type , n : int , m : int , callee : CallableType ,
1634- context : Context , messages : MessageBuilder ) -> None :
1635- nonlocal ok
1636- if not is_subtype (caller_type , callee_type ):
1637- ok = False
1638-
1639- self .check_argument_types (arg_types , arg_kinds , callee , formal_to_actual ,
1640- context = context , check_arg = check_arg )
1641- return ok
1605+ return False
16421606
16431607 def apply_generic_arguments (self , callable : CallableType , types : Sequence [Optional [Type ]],
16441608 context : Context ) -> CallableType :
@@ -3399,101 +3363,68 @@ def visit_uninhabited_type(self, t: UninhabitedType) -> bool:
33993363 return True
34003364
34013365
3402- def overload_arg_similarity (actual : Type , formal : Type ) -> int :
3403- """Return if caller argument (actual) is compatible with overloaded signature arg (formal).
3366+ def arg_approximate_similarity (actual : Type , formal : Type ) -> bool :
3367+ """Return if caller argument (actual) is roughly compatible with signature arg (formal).
34043368
3405- Return a similarity level:
3406- 0: no match
3407- 1: actual is compatible, but only using type promotions (e.g. int vs float)
3408- 2: actual is compatible without type promotions (e.g. int vs object)
3369+ This function is deliberately loose and will report two types are similar
3370+ as long as their "shapes" are plausibly the same.
34093371
3410- The distinction is important in cases where multiple overload items match. We want
3411- give priority to higher similarity matches.
3372+ This is useful when we're doing error reporting: for example, if we're trying
3373+ to select an overload alternative and there's no exact match, we can use
3374+ this function to help us identify which alternative the user might have
3375+ *meant* to match.
34123376 """
3413- # Replace type variables with their upper bounds. Overloading
3414- # resolution is based on runtime behavior which erases type
3415- # parameters, so no need to handle type variables occurring within
3416- # a type.
3377+
3378+ # Erase typevars: we'll consider them all to have the same "shape".
3379+
34173380 if isinstance (actual , TypeVarType ):
34183381 actual = actual .erase_to_union_or_bound ()
34193382 if isinstance (formal , TypeVarType ):
34203383 formal = formal .erase_to_union_or_bound ()
3421- if (isinstance (actual , UninhabitedType ) or isinstance (actual , AnyType ) or
3422- isinstance (formal , AnyType ) or
3423- (isinstance (actual , Instance ) and actual .type .fallback_to_any )):
3424- # These could match anything at runtime.
3425- return 2
3384+
3385+ # Callable or Type[...]-ish types
3386+
3387+ def is_typetype_like (typ : Type ) -> bool :
3388+ return (isinstance (typ , TypeType )
3389+ or (isinstance (typ , FunctionLike ) and typ .is_type_obj ())
3390+ or (isinstance (typ , Instance ) and typ .type .fullname () == "builtins.type" ))
3391+
34263392 if isinstance (formal , CallableType ):
3427- if isinstance (actual , (CallableType , Overloaded )):
3428- # TODO: do more sophisticated callable matching
3429- return 2
3430- if isinstance (actual , TypeType ):
3431- return 2 if is_subtype (actual , formal ) else 0
3432- if isinstance (actual , NoneTyp ):
3433- if not experiments .STRICT_OPTIONAL :
3434- # NoneTyp matches anything if we're not doing strict Optional checking
3435- return 2
3436- else :
3437- # NoneType is a subtype of object
3438- if isinstance (formal , Instance ) and formal .type .fullname () == "builtins.object" :
3439- return 2
3393+ if isinstance (actual , (CallableType , Overloaded , TypeType )):
3394+ return True
3395+ if is_typetype_like (actual ) and is_typetype_like (formal ):
3396+ return True
3397+
3398+ # Unions
3399+
34403400 if isinstance (actual , UnionType ):
3441- return max (overload_arg_similarity (item , formal )
3442- for item in actual .relevant_items ())
3401+ return any (arg_approximate_similarity (item , formal ) for item in actual .relevant_items ())
34433402 if isinstance (formal , UnionType ):
3444- return max (overload_arg_similarity (actual , item )
3445- for item in formal .relevant_items ())
3446- if isinstance (formal , TypeType ):
3447- if isinstance (actual , TypeType ):
3448- # Since Type[T] is covariant, check if actual = Type[A] is
3449- # a subtype of formal = Type[F].
3450- return overload_arg_similarity (actual .item , formal .item )
3451- elif isinstance (actual , FunctionLike ) and actual .is_type_obj ():
3452- # Check if the actual is a constructor of some sort.
3453- # Note that this is this unsound, since we don't check the __init__ signature.
3454- return overload_arg_similarity (actual .items ()[0 ].ret_type , formal .item )
3455- else :
3456- return 0
3403+ return any (arg_approximate_similarity (actual , item ) for item in formal .relevant_items ())
3404+
3405+ # TypedDicts
3406+
34573407 if isinstance (actual , TypedDictType ):
34583408 if isinstance (formal , TypedDictType ):
3459- # Don't support overloading based on the keys or value types of a TypedDict since
3460- # that would be complicated and probably only marginally useful.
3461- return 2
3462- return overload_arg_similarity (actual .fallback , formal )
3409+ return True
3410+ return arg_approximate_similarity (actual .fallback , formal )
3411+
3412+ # Instances
3413+ # For instances, we mostly defer to the existing is_subtype check.
3414+
34633415 if isinstance (formal , Instance ):
34643416 if isinstance (actual , CallableType ):
34653417 actual = actual .fallback
34663418 if isinstance (actual , Overloaded ):
34673419 actual = actual .items ()[0 ].fallback
34683420 if isinstance (actual , TupleType ):
34693421 actual = actual .fallback
3470- if isinstance (actual , Instance ):
3471- # First perform a quick check (as an optimization) and fall back to generic
3472- # subtyping algorithm if type promotions are possible (e.g., int vs. float).
3473- if formal .type in actual .type .mro :
3474- return 2
3475- elif formal .type .is_protocol and is_subtype (actual , erasetype .erase_type (formal )):
3476- return 2
3477- elif actual .type ._promote and is_subtype (actual , formal ):
3478- return 1
3479- else :
3480- return 0
3481- elif isinstance (actual , TypeType ):
3482- item = actual .item
3483- if formal .type .fullname () in {"builtins.object" , "builtins.type" }:
3484- return 2
3485- elif isinstance (item , Instance ) and item .type .metaclass_type :
3486- # FIX: this does not handle e.g. Union of instances
3487- return overload_arg_similarity (item .type .metaclass_type , formal )
3488- else :
3489- return 0
3490- else :
3491- return 0
3492- if isinstance (actual , UnboundType ) or isinstance (formal , UnboundType ):
3493- # Either actual or formal is the result of an error; shut up.
3494- return 2
3495- # Fall back to a conservative equality check for the remaining kinds of type.
3496- return 2 if is_same_type (erasetype .erase_type (actual ), erasetype .erase_type (formal )) else 0
3422+ if isinstance (actual , Instance ) and formal .type in actual .type .mro :
3423+ # Try performing a quick check as an optimization
3424+ return True
3425+
3426+ # Fall back to a standard subtype check for the remaining kinds of type.
3427+ return is_subtype (erasetype .erase_type (actual ), erasetype .erase_type (formal ))
34973428
34983429
34993430def any_causes_overload_ambiguity (items : List [CallableType ],
0 commit comments