@@ -306,6 +306,19 @@ def is_none_object_overlap(t1: ProperType, t2: ProperType) -> bool:
306
306
)
307
307
308
308
309
+ def are_related_types (
310
+ left : Type , right : Type , * , proper_subtype : bool , ignore_promotions : bool
311
+ ) -> bool :
312
+ if proper_subtype :
313
+ return is_proper_subtype (
314
+ left , right , ignore_promotions = ignore_promotions
315
+ ) or is_proper_subtype (right , left , ignore_promotions = ignore_promotions )
316
+ else :
317
+ return is_subtype (left , right , ignore_promotions = ignore_promotions ) or is_subtype (
318
+ right , left , ignore_promotions = ignore_promotions
319
+ )
320
+
321
+
309
322
def is_overlapping_types (
310
323
left : Type ,
311
324
right : Type ,
@@ -329,27 +342,13 @@ def is_overlapping_types(
329
342
330
343
if seen_types is None :
331
344
seen_types = set ()
332
- if (left , right ) in seen_types :
345
+ elif (left , right ) in seen_types :
333
346
return True
334
347
if isinstance (left , TypeAliasType ) and isinstance (right , TypeAliasType ):
335
348
seen_types .add ((left , right ))
336
349
337
350
left , right = get_proper_types ((left , right ))
338
351
339
- def _is_overlapping_types (left : Type , right : Type ) -> bool :
340
- """Encode the kind of overlapping check to perform.
341
-
342
- This function mostly exists, so we don't have to repeat keyword arguments everywhere.
343
- """
344
- return is_overlapping_types (
345
- left ,
346
- right ,
347
- ignore_promotions = ignore_promotions ,
348
- prohibit_none_typevar_overlap = prohibit_none_typevar_overlap ,
349
- overlap_for_overloads = overlap_for_overloads ,
350
- seen_types = seen_types .copy (),
351
- )
352
-
353
352
# We should never encounter this type.
354
353
if isinstance (left , PartialType ) or isinstance (right , PartialType ):
355
354
assert False , "Unexpectedly encountered partial type"
@@ -399,13 +398,9 @@ def _is_overlapping_types(left: Type, right: Type) -> bool:
399
398
if is_none_object_overlap (left , right ) or is_none_object_overlap (right , left ):
400
399
return False
401
400
402
- def _is_subtype (left : Type , right : Type ) -> bool :
403
- if overlap_for_overloads :
404
- return is_proper_subtype (left , right , ignore_promotions = ignore_promotions )
405
- else :
406
- return is_subtype (left , right , ignore_promotions = ignore_promotions )
407
-
408
- if _is_subtype (left , right ) or _is_subtype (right , left ):
401
+ if are_related_types (
402
+ left , right , proper_subtype = overlap_for_overloads , ignore_promotions = ignore_promotions
403
+ ):
409
404
return True
410
405
411
406
# See the docstring for 'get_possible_variants' for more info on what the
@@ -428,6 +423,20 @@ def _is_subtype(left: Type, right: Type) -> bool:
428
423
if is_none_typevarlike_overlap (left , right ) or is_none_typevarlike_overlap (right , left ):
429
424
return False
430
425
426
+ def _is_overlapping_types (left : Type , right : Type ) -> bool :
427
+ """Encode the kind of overlapping check to perform.
428
+
429
+ This function mostly exists, so we don't have to repeat keyword arguments everywhere.
430
+ """
431
+ return is_overlapping_types (
432
+ left ,
433
+ right ,
434
+ ignore_promotions = ignore_promotions ,
435
+ prohibit_none_typevar_overlap = prohibit_none_typevar_overlap ,
436
+ overlap_for_overloads = overlap_for_overloads ,
437
+ seen_types = seen_types .copy (),
438
+ )
439
+
431
440
if (
432
441
len (left_possible ) > 1
433
442
or len (right_possible ) > 1
@@ -483,27 +492,28 @@ def _is_subtype(left: Type, right: Type) -> bool:
483
492
if isinstance (left , TypeType ) and isinstance (right , TypeType ):
484
493
return _is_overlapping_types (left .item , right .item )
485
494
486
- def _type_object_overlap (left : Type , right : Type ) -> bool :
487
- """Special cases for type object types overlaps."""
488
- # TODO: these checks are a bit in gray area, adjust if they cause problems.
489
- left , right = get_proper_types ((left , right ))
490
- # 1. Type[C] vs Callable[..., C] overlap even if the latter is not class object.
491
- if isinstance (left , TypeType ) and isinstance (right , CallableType ):
492
- return _is_overlapping_types (left .item , right .ret_type )
493
- # 2. Type[C] vs Meta, where Meta is a metaclass for C.
494
- if isinstance (left , TypeType ) and isinstance (right , Instance ):
495
- if isinstance (left .item , Instance ):
496
- left_meta = left .item .type .metaclass_type
497
- if left_meta is not None :
498
- return _is_overlapping_types (left_meta , right )
499
- # builtins.type (default metaclass) overlaps with all metaclasses
500
- return right .type .has_base ("builtins.type" )
501
- elif isinstance (left .item , AnyType ):
502
- return right .type .has_base ("builtins.type" )
503
- # 3. Callable[..., C] vs Meta is considered below, when we switch to fallbacks.
504
- return False
505
-
506
495
if isinstance (left , TypeType ) or isinstance (right , TypeType ):
496
+
497
+ def _type_object_overlap (left : Type , right : Type ) -> bool :
498
+ """Special cases for type object types overlaps."""
499
+ # TODO: these checks are a bit in gray area, adjust if they cause problems.
500
+ left , right = get_proper_types ((left , right ))
501
+ # 1. Type[C] vs Callable[..., C] overlap even if the latter is not class object.
502
+ if isinstance (left , TypeType ) and isinstance (right , CallableType ):
503
+ return _is_overlapping_types (left .item , right .ret_type )
504
+ # 2. Type[C] vs Meta, where Meta is a metaclass for C.
505
+ if isinstance (left , TypeType ) and isinstance (right , Instance ):
506
+ if isinstance (left .item , Instance ):
507
+ left_meta = left .item .type .metaclass_type
508
+ if left_meta is not None :
509
+ return _is_overlapping_types (left_meta , right )
510
+ # builtins.type (default metaclass) overlaps with all metaclasses
511
+ return right .type .has_base ("builtins.type" )
512
+ elif isinstance (left .item , AnyType ):
513
+ return right .type .has_base ("builtins.type" )
514
+ # 3. Callable[..., C] vs Meta is considered below, when we switch to fallbacks.
515
+ return False
516
+
507
517
return _type_object_overlap (left , right ) or _type_object_overlap (right , left )
508
518
509
519
if isinstance (left , Parameters ) and isinstance (right , Parameters ):
@@ -564,7 +574,9 @@ def _type_object_overlap(left: Type, right: Type) -> bool:
564
574
if isinstance (left , Instance ) and isinstance (right , Instance ):
565
575
# First we need to handle promotions and structural compatibility for instances
566
576
# that came as fallbacks, so simply call is_subtype() to avoid code duplication.
567
- if _is_subtype (left , right ) or _is_subtype (right , left ):
577
+ if are_related_types (
578
+ left , right , proper_subtype = overlap_for_overloads , ignore_promotions = ignore_promotions
579
+ ):
568
580
return True
569
581
570
582
if right .type .fullname == "builtins.int" and left .type .fullname in MYPYC_NATIVE_INT_NAMES :
0 commit comments