@@ -1575,12 +1575,9 @@ def union_overload_matches(self, types: Sequence[Type]) -> Union[AnyType, Callab
1575
1575
def erased_signature_similarity (self , arg_types : List [Type ], arg_kinds : List [int ],
1576
1576
arg_names : Optional [Sequence [Optional [str ]]],
1577
1577
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."""
1584
1581
formal_to_actual = map_actuals_to_formals (arg_kinds ,
1585
1582
arg_names ,
1586
1583
callee .arg_kinds ,
@@ -1590,55 +1587,22 @@ def erased_signature_similarity(self, arg_types: List[Type], arg_kinds: List[int
1590
1587
if not self .check_argument_count (callee , arg_types , arg_kinds , arg_names ,
1591
1588
formal_to_actual , None , None ):
1592
1589
# Too few or many arguments -> no match.
1593
- return 0
1594
-
1595
- similarity = 2
1590
+ return False
1596
1591
1597
1592
def check_arg (caller_type : Type , original_caller_type : Type , caller_kind : int ,
1598
1593
callee_type : Type , n : int , m : int , callee : CallableType ,
1599
1594
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 ):
1604
1596
# No match -- exit early since none of the remaining work can change
1605
1597
# the result.
1606
1598
raise Finished
1607
1599
1608
1600
try :
1609
1601
self .check_argument_types (arg_types , arg_kinds , callee , formal_to_actual ,
1610
1602
context = context , check_arg = check_arg )
1603
+ return True
1611
1604
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
1642
1606
1643
1607
def apply_generic_arguments (self , callable : CallableType , types : Sequence [Optional [Type ]],
1644
1608
context : Context ) -> CallableType :
@@ -3399,101 +3363,68 @@ def visit_uninhabited_type(self, t: UninhabitedType) -> bool:
3399
3363
return True
3400
3364
3401
3365
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).
3404
3368
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.
3409
3371
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.
3412
3376
"""
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
+
3417
3380
if isinstance (actual , TypeVarType ):
3418
3381
actual = actual .erase_to_union_or_bound ()
3419
3382
if isinstance (formal , TypeVarType ):
3420
3383
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
+
3426
3392
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
+
3440
3400
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 ())
3443
3402
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
+
3457
3407
if isinstance (actual , TypedDictType ):
3458
3408
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
+
3463
3415
if isinstance (formal , Instance ):
3464
3416
if isinstance (actual , CallableType ):
3465
3417
actual = actual .fallback
3466
3418
if isinstance (actual , Overloaded ):
3467
3419
actual = actual .items ()[0 ].fallback
3468
3420
if isinstance (actual , TupleType ):
3469
3421
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 ))
3497
3428
3498
3429
3499
3430
def any_causes_overload_ambiguity (items : List [CallableType ],
0 commit comments