@@ -119,6 +119,11 @@ impl Context {
119119 self . supertype_of ( lhs, rhs) || self . subtype_of ( lhs, rhs)
120120 }
121121
122+ pub ( crate ) fn _related_tp ( & self , lhs : & TyParam , rhs : & TyParam ) -> bool {
123+ self . _subtype_of_tp ( lhs, rhs, Variance :: Covariant )
124+ || self . supertype_of_tp ( lhs, rhs, Variance :: Covariant )
125+ }
126+
122127 /// lhs :> rhs ?
123128 pub ( crate ) fn supertype_of ( & self , lhs : & Type , rhs : & Type ) -> bool {
124129 let res = match Self :: cheap_supertype_of ( lhs, rhs) {
@@ -1118,6 +1123,10 @@ impl Context {
11181123 }
11191124 }
11201125
1126+ pub ( crate ) fn covariant_supertype_of_tp ( & self , lp : & TyParam , rp : & TyParam ) -> bool {
1127+ self . supertype_of_tp ( lp, rp, Variance :: Covariant )
1128+ }
1129+
11211130 /// lhs <: rhs?
11221131 pub ( crate ) fn structural_subtype_of ( & self , lhs : & Type , rhs : & Type ) -> bool {
11231132 self . structural_supertype_of ( rhs, lhs)
@@ -1282,6 +1291,7 @@ impl Context {
12821291 /// union(Array(Int, 2), Array(Str, 3)) == Array(Int, 2) or Array(Int, 3)
12831292 /// union({ .a = Int }, { .a = Str }) == { .a = Int or Str }
12841293 /// union({ .a = Int }, { .a = Int; .b = Int }) == { .a = Int }
1294+ /// union((A and B) or C) == (A or C) and (B or C)
12851295 /// ```
12861296 pub ( crate ) fn union ( & self , lhs : & Type , rhs : & Type ) -> Type {
12871297 if lhs == rhs {
@@ -1345,6 +1355,16 @@ impl Context {
13451355 _ => self . simple_union ( lhs, rhs) ,
13461356 } ,
13471357 ( other, or @ Or ( _, _) ) | ( or @ Or ( _, _) , other) => self . union_add ( or, other) ,
1358+ // (A and B) or C ==> (A or C) and (B or C)
1359+ ( and_t @ And ( _, _) , other) | ( other, and_t @ And ( _, _) ) => {
1360+ let ands = and_t. ands ( ) ;
1361+ let mut t = Type :: Obj ;
1362+ for branch in ands. iter ( ) {
1363+ let union = self . union ( branch, other) ;
1364+ t = and ( t, union) ;
1365+ }
1366+ t
1367+ }
13481368 ( t, Type :: Never ) | ( Type :: Never , t) => t. clone ( ) ,
13491369 // Array({1, 2}, 2), Array({3, 4}, 2) ==> Array({1, 2, 3, 4}, 2)
13501370 (
@@ -1497,12 +1517,6 @@ impl Context {
14971517 self . intersection ( & fv. crack ( ) , other)
14981518 }
14991519 ( Refinement ( l) , Refinement ( r) ) => Type :: Refinement ( self . intersection_refinement ( l, r) ) ,
1500- ( other, Refinement ( refine) ) | ( Refinement ( refine) , other) => {
1501- let other = other. clone ( ) . into_refinement ( ) ;
1502- let intersec = self . intersection_refinement ( & other, refine) ;
1503- self . try_squash_refinement ( intersec)
1504- . unwrap_or_else ( Type :: Refinement )
1505- }
15061520 ( Structural ( l) , Structural ( r) ) => self . intersection ( l, r) . structuralize ( ) ,
15071521 ( Guard ( l) , Guard ( r) ) => {
15081522 if l. namespace == r. namespace && l. target == r. target {
@@ -1527,6 +1541,25 @@ impl Context {
15271541 ( other, and @ And ( _, _) ) | ( and @ And ( _, _) , other) => {
15281542 self . intersection_add ( and, other)
15291543 }
1544+ // (A or B) and C == (A and C) or (B and C)
1545+ ( or_t @ Or ( _, _) , other) | ( other, or_t @ Or ( _, _) ) => {
1546+ let ors = or_t. ors ( ) ;
1547+ if ors. iter ( ) . any ( |t| t. has_unbound_var ( ) ) {
1548+ return self . simple_intersection ( lhs, rhs) ;
1549+ }
1550+ let mut t = Type :: Never ;
1551+ for branch in ors. iter ( ) {
1552+ let isec = self . intersection ( branch, other) ;
1553+ t = self . union ( & t, & isec) ;
1554+ }
1555+ t
1556+ }
1557+ ( other, Refinement ( refine) ) | ( Refinement ( refine) , other) => {
1558+ let other = other. clone ( ) . into_refinement ( ) ;
1559+ let intersec = self . intersection_refinement ( & other, refine) ;
1560+ self . try_squash_refinement ( intersec)
1561+ . unwrap_or_else ( Type :: Refinement )
1562+ }
15301563 // overloading
15311564 ( l, r) if l. is_subr ( ) && r. is_subr ( ) => and ( lhs. clone ( ) , rhs. clone ( ) ) ,
15321565 _ => self . simple_intersection ( lhs, rhs) ,
0 commit comments