11
11
from collections import defaultdict
12
12
from typing import Any , Callable , Iterable , List , Sequence , TypeVar , cast
13
13
14
+ import mypy .checker
14
15
from mypy .copytype import copy_type
15
16
from mypy .expandtype import expand_type , expand_type_by_instance
16
17
from mypy .maptype import map_instance_to_supertype
18
+ from mypy .mro import MroError , calculate_mro
17
19
from mypy .nodes import (
18
20
ARG_POS ,
19
21
ARG_STAR ,
@@ -568,7 +570,12 @@ def _remove_redundant_union_items(items: list[Type], keep_erased: bool) -> list[
568
570
569
571
570
572
def make_simplified_intersection (
571
- items : Sequence [Type ], line : int = - 1 , column : int = - 1 , * , keep_erased : bool = False
573
+ items : Sequence [Type ],
574
+ line : int = - 1 ,
575
+ column : int = - 1 ,
576
+ * ,
577
+ keep_erased : bool = False ,
578
+ check : mypy .checker .TypeChecker | None = None ,
572
579
) -> ProperType :
573
580
"""Build intersection type with redundant intersection items removed.
574
581
@@ -582,6 +589,7 @@ def make_simplified_intersection(
582
589
* [int, Any] -> Intersection[int, Any] (Any types are not simplified away!)
583
590
* [Any, Any] -> Any
584
591
* [int, Intersection[bytes, str]] -> Intersection[int, bytes, str]
592
+ * [int, str] -> Never (invalid types become Never!)
585
593
586
594
Note: This must NOT be used during semantic analysis, since TypeInfos may not
587
595
be fully initialized.
@@ -599,6 +607,24 @@ def make_simplified_intersection(
599
607
# Step 3: remove redundant intersections
600
608
simplified_set : Sequence [Type ] = _remove_redundant_intersection_items (items , keep_erased )
601
609
610
+ if len (items ) == 1 :
611
+ return get_proper_type (items [0 ])
612
+
613
+ for item in items :
614
+ if isinstance (item , Instance ):
615
+ if item .type .is_final :
616
+ return UninhabitedType ()
617
+ if isinstance (item , LiteralType ):
618
+ return UninhabitedType ()
619
+
620
+ if check :
621
+ for i in range (len (simplified_set )):
622
+ for j in range (len (simplified_set ))[i :]:
623
+ l = simplified_set [i ]
624
+ r = simplified_set [j ]
625
+ if isinstance (l , Instance ) and isinstance (r , Instance ):
626
+ if _check_invalid_intersection ((l , r ), check ):
627
+ return UninhabitedType ()
602
628
result = get_proper_type (IntersectionType .make_intersection (simplified_set , line , column ))
603
629
604
630
# Step 5: At last, we erase any (inconsistent) extra attributes on instances.
@@ -645,6 +671,53 @@ def _remove_redundant_intersection_items(items: list[Type], keep_erased: bool) -
645
671
return [items [i ] for i in range (len (items )) if i not in removed ]
646
672
647
673
674
+ def _check_invalid_intersection (
675
+ instances : (Instance , Instance ), check : mypy .checker .TypeChecker
676
+ ) -> bool :
677
+ def _get_base_classes (instances_ : (Instance , Instance )) -> list [Instance ]:
678
+ base_classes_ = []
679
+ for inst in instances_ :
680
+ if inst .type .is_intersection :
681
+ expanded = inst .type .bases
682
+ else :
683
+ expanded = [inst ]
684
+
685
+ for expanded_inst in expanded :
686
+ base_classes_ .append (expanded_inst )
687
+ return base_classes_
688
+
689
+ def make_fake_typeinfo (bases : list [Instance ]) -> TypeInfo :
690
+ from mypy .nodes import Block , ClassDef , SymbolTable
691
+
692
+ cdef = ClassDef ("sus" , Block ([]))
693
+ info = TypeInfo (SymbolTable (), cdef , "amongus" )
694
+ info .bases = bases
695
+ calculate_mro (info )
696
+ info .metaclass_type = info .calculate_metaclass_type ()
697
+ return info
698
+
699
+ base_classes = _get_base_classes (instances )
700
+
701
+ bases = base_classes
702
+ try :
703
+ info = make_fake_typeinfo (bases )
704
+ with check .msg .filter_errors () as local_errors :
705
+ check .check_multiple_inheritance (info )
706
+ if local_errors .has_new_errors ():
707
+ # "class A(B, C)" unsafe, now check "class A(C, B)":
708
+ base_classes = _get_base_classes (instances [::- 1 ])
709
+ info = make_fake_typeinfo (base_classes )
710
+ with check .msg .filter_errors () as local_errors :
711
+ check .check_multiple_inheritance (info )
712
+ info .is_intersection = True
713
+ except MroError :
714
+ return True
715
+ if local_errors .has_new_errors ():
716
+ return True
717
+
718
+ return False
719
+
720
+
648
721
def _get_type_special_method_bool_ret_type (t : Type ) -> Type | None :
649
722
t = get_proper_type (t )
650
723
0 commit comments