@@ -306,6 +306,19 @@ def is_none_object_overlap(t1: ProperType, t2: ProperType) -> bool:
306306 )
307307
308308
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+
309322def is_overlapping_types (
310323 left : Type ,
311324 right : Type ,
@@ -329,27 +342,13 @@ def is_overlapping_types(
329342
330343 if seen_types is None :
331344 seen_types = set ()
332- if (left , right ) in seen_types :
345+ elif (left , right ) in seen_types :
333346 return True
334347 if isinstance (left , TypeAliasType ) and isinstance (right , TypeAliasType ):
335348 seen_types .add ((left , right ))
336349
337350 left , right = get_proper_types ((left , right ))
338351
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-
353352 # We should never encounter this type.
354353 if isinstance (left , PartialType ) or isinstance (right , PartialType ):
355354 assert False , "Unexpectedly encountered partial type"
@@ -399,13 +398,9 @@ def _is_overlapping_types(left: Type, right: Type) -> bool:
399398 if is_none_object_overlap (left , right ) or is_none_object_overlap (right , left ):
400399 return False
401400
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+ ):
409404 return True
410405
411406 # 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:
428423 if is_none_typevarlike_overlap (left , right ) or is_none_typevarlike_overlap (right , left ):
429424 return False
430425
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+
431440 if (
432441 len (left_possible ) > 1
433442 or len (right_possible ) > 1
@@ -483,27 +492,28 @@ def _is_subtype(left: Type, right: Type) -> bool:
483492 if isinstance (left , TypeType ) and isinstance (right , TypeType ):
484493 return _is_overlapping_types (left .item , right .item )
485494
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-
506495 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+
507517 return _type_object_overlap (left , right ) or _type_object_overlap (right , left )
508518
509519 if isinstance (left , Parameters ) and isinstance (right , Parameters ):
@@ -564,7 +574,9 @@ def _type_object_overlap(left: Type, right: Type) -> bool:
564574 if isinstance (left , Instance ) and isinstance (right , Instance ):
565575 # First we need to handle promotions and structural compatibility for instances
566576 # 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+ ):
568580 return True
569581
570582 if right .type .fullname == "builtins.int" and left .type .fullname in MYPYC_NATIVE_INT_NAMES :
0 commit comments