@@ -824,11 +824,9 @@ impl<'db> Type<'db> {
824824 /// - Literal[True, False] | T <: bool | T
825825 #[ must_use]
826826 pub fn with_normalized_bools ( self , db : & ' db dyn Db ) -> Self {
827- const LITERAL_BOOLS : [ Type ; 2 ] = [ Type :: BooleanLiteral ( false ) , Type :: BooleanLiteral ( true ) ] ;
828-
829827 match self {
830828 Type :: Instance ( InstanceType { class } ) if class. is_known ( db, KnownClass :: Bool ) => {
831- Type :: Union ( UnionType :: new ( db , Box :: from ( LITERAL_BOOLS ) ) )
829+ Type :: normalized_bool ( db )
832830 }
833831 // TODO: decompose `LiteralString` into `Literal[""] | TruthyLiteralString`?
834832 // We'd need to rename this method... --Alex
@@ -884,12 +882,6 @@ impl<'db> Type<'db> {
884882 return true ;
885883 }
886884
887- let normalized_self = self . with_normalized_bools ( db) ;
888- let normalized_target = target. with_normalized_bools ( db) ;
889- if normalized_self != self || normalized_target != target {
890- return normalized_self. is_subtype_of ( db, normalized_target) ;
891- }
892-
893885 // Non-fully-static types do not participate in subtyping.
894886 //
895887 // Type `A` can only be a subtype of type `B` if the set of possible runtime objects
@@ -912,6 +904,13 @@ impl<'db> Type<'db> {
912904 ( Type :: Never , _) => true ,
913905 ( _, Type :: Never ) => false ,
914906
907+ ( Type :: Instance ( InstanceType { class } ) , _) if class. is_known ( db, KnownClass :: Bool ) => {
908+ Type :: normalized_bool ( db) . is_subtype_of ( db, target)
909+ }
910+ ( _, Type :: Instance ( InstanceType { class } ) ) if class. is_known ( db, KnownClass :: Bool ) => {
911+ self . is_subtype_of ( db, Type :: normalized_bool ( db) )
912+ }
913+
915914 ( Type :: Union ( union) , _) => union
916915 . elements ( db)
917916 . iter ( )
@@ -1108,11 +1107,7 @@ impl<'db> Type<'db> {
11081107 if self . is_gradual_equivalent_to ( db, target) {
11091108 return true ;
11101109 }
1111- let normalized_self = self . with_normalized_bools ( db) ;
1112- let normalized_target = target. with_normalized_bools ( db) ;
1113- if normalized_self != self || normalized_target != target {
1114- return normalized_self. is_assignable_to ( db, normalized_target) ;
1115- }
1110+
11161111 match ( self , target) {
11171112 // Never can be assigned to any type.
11181113 ( Type :: Never , _) => true ,
@@ -1129,6 +1124,13 @@ impl<'db> Type<'db> {
11291124 true
11301125 }
11311126
1127+ ( Type :: Instance ( InstanceType { class } ) , _) if class. is_known ( db, KnownClass :: Bool ) => {
1128+ Type :: normalized_bool ( db) . is_assignable_to ( db, target)
1129+ }
1130+ ( _, Type :: Instance ( InstanceType { class } ) ) if class. is_known ( db, KnownClass :: Bool ) => {
1131+ self . is_assignable_to ( db, Type :: normalized_bool ( db) )
1132+ }
1133+
11321134 // A union is assignable to a type T iff every element of the union is assignable to T.
11331135 ( Type :: Union ( union) , ty) => union
11341136 . elements ( db)
@@ -1213,13 +1215,6 @@ impl<'db> Type<'db> {
12131215 pub ( crate ) fn is_equivalent_to ( self , db : & ' db dyn Db , other : Type < ' db > ) -> bool {
12141216 // TODO equivalent but not identical types: TypedDicts, Protocols, type aliases, etc.
12151217
1216- let normalized_self = self . with_normalized_bools ( db) ;
1217- let normalized_other = other. with_normalized_bools ( db) ;
1218-
1219- if normalized_self != self || normalized_other != other {
1220- return normalized_self. is_equivalent_to ( db, normalized_other) ;
1221- }
1222-
12231218 match ( self , other) {
12241219 ( Type :: Union ( left) , Type :: Union ( right) ) => left. is_equivalent_to ( db, right) ,
12251220 ( Type :: Intersection ( left) , Type :: Intersection ( right) ) => {
@@ -1261,13 +1256,6 @@ impl<'db> Type<'db> {
12611256 ///
12621257 /// [Summary of type relations]: https://typing.readthedocs.io/en/latest/spec/concepts.html#summary-of-type-relations
12631258 pub ( crate ) fn is_gradual_equivalent_to ( self , db : & ' db dyn Db , other : Type < ' db > ) -> bool {
1264- let normalized_self = self . with_normalized_bools ( db) ;
1265- let normalized_other = other. with_normalized_bools ( db) ;
1266-
1267- if normalized_self != self || normalized_other != other {
1268- return normalized_self. is_gradual_equivalent_to ( db, normalized_other) ;
1269- }
1270-
12711259 if self == other {
12721260 return true ;
12731261 }
@@ -1300,12 +1288,6 @@ impl<'db> Type<'db> {
13001288 /// Note: This function aims to have no false positives, but might return
13011289 /// wrong `false` answers in some cases.
13021290 pub ( crate ) fn is_disjoint_from ( self , db : & ' db dyn Db , other : Type < ' db > ) -> bool {
1303- let normalized_self = self . with_normalized_bools ( db) ;
1304- let normalized_other = other. with_normalized_bools ( db) ;
1305- if normalized_self != self || normalized_other != other {
1306- return normalized_self. is_disjoint_from ( db, normalized_other) ;
1307- }
1308-
13091291 match ( self , other) {
13101292 ( Type :: Never , _) | ( _, Type :: Never ) => true ,
13111293
@@ -2427,6 +2409,13 @@ impl<'db> Type<'db> {
24272409 KnownClass :: NoneType . to_instance ( db)
24282410 }
24292411
2412+ /// The type `Literal[True, False]`, which is exactly equivalent to `bool`
2413+ /// (and which `bool` is eagerly normalized to in several situations)
2414+ pub fn normalized_bool ( db : & ' db dyn Db ) -> Type < ' db > {
2415+ const LITERAL_BOOLS : [ Type ; 2 ] = [ Type :: BooleanLiteral ( false ) , Type :: BooleanLiteral ( true ) ] ;
2416+ Type :: Union ( UnionType :: new ( db, Box :: from ( LITERAL_BOOLS ) ) )
2417+ }
2418+
24302419 /// Return the type of `tuple(sys.version_info)`.
24312420 ///
24322421 /// This is not exactly the type that `sys.version_info` has at runtime,
@@ -4698,19 +4687,18 @@ pub struct TupleType<'db> {
46984687}
46994688
47004689impl < ' db > TupleType < ' db > {
4701- pub fn from_elements < I , T > ( db : & ' db dyn Db , types : I ) -> Type < ' db >
4702- where
4703- I : IntoIterator < Item = T > ,
4704- T : Into < Type < ' db > > ,
4705- {
4690+ pub fn from_elements < T : Into < Type < ' db > > > (
4691+ db : & ' db dyn Db ,
4692+ types : impl IntoIterator < Item = T > ,
4693+ ) -> Type < ' db > {
47064694 let mut elements = vec ! [ ] ;
47074695
47084696 for ty in types {
4709- let ty: Type < ' db > = ty. into ( ) ;
4697+ let ty = ty. into ( ) ;
47104698 if ty. is_never ( ) {
47114699 return Type :: Never ;
47124700 }
4713- elements. push ( ty. with_normalized_bools ( db ) ) ;
4701+ elements. push ( ty) ;
47144702 }
47154703
47164704 Type :: Tuple ( Self :: new ( db, elements. into_boxed_slice ( ) ) )
0 commit comments