@@ -1282,6 +1282,7 @@ impl Context {
12821282 /// union(Array(Int, 2), Array(Str, 3)) == Array(Int, 2) or Array(Int, 3)
12831283 /// union({ .a = Int }, { .a = Str }) == { .a = Int or Str }
12841284 /// union({ .a = Int }, { .a = Int; .b = Int }) == { .a = Int }
1285+ /// union((A and B) or C) == (A or C) and (B or C)
12851286 /// ```
12861287 pub ( crate ) fn union ( & self , lhs : & Type , rhs : & Type ) -> Type {
12871288 if lhs == rhs {
@@ -1345,6 +1346,16 @@ impl Context {
13451346 _ => self . simple_union ( lhs, rhs) ,
13461347 } ,
13471348 ( other, or @ Or ( _, _) ) | ( or @ Or ( _, _) , other) => self . union_add ( or, other) ,
1349+ // (A and B) or C ==> (A or C) and (B or C)
1350+ ( and_t @ And ( _, _) , other) | ( other, and_t @ And ( _, _) ) => {
1351+ let ands = and_t. ands ( ) ;
1352+ let mut t = Type :: Obj ;
1353+ for branch in ands. iter ( ) {
1354+ let union = self . union ( branch, other) ;
1355+ t = and ( t, union) ;
1356+ }
1357+ t
1358+ }
13481359 ( t, Type :: Never ) | ( Type :: Never , t) => t. clone ( ) ,
13491360 // Array({1, 2}, 2), Array({3, 4}, 2) ==> Array({1, 2, 3, 4}, 2)
13501361 (
@@ -1497,12 +1508,6 @@ impl Context {
14971508 self . intersection ( & fv. crack ( ) , other)
14981509 }
14991510 ( 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- }
15061511 ( Structural ( l) , Structural ( r) ) => self . intersection ( l, r) . structuralize ( ) ,
15071512 ( Guard ( l) , Guard ( r) ) => {
15081513 if l. namespace == r. namespace && l. target == r. target {
@@ -1527,6 +1532,25 @@ impl Context {
15271532 ( other, and @ And ( _, _) ) | ( and @ And ( _, _) , other) => {
15281533 self . intersection_add ( and, other)
15291534 }
1535+ // (A or B) and C == (A and C) or (B and C)
1536+ ( or_t @ Or ( _, _) , other) | ( other, or_t @ Or ( _, _) ) => {
1537+ let ors = or_t. ors ( ) ;
1538+ if ors. iter ( ) . any ( |t| t. has_unbound_var ( ) ) {
1539+ return self . simple_intersection ( lhs, rhs) ;
1540+ }
1541+ let mut t = Type :: Never ;
1542+ for branch in ors. iter ( ) {
1543+ let isec = self . intersection ( branch, other) ;
1544+ t = self . union ( & t, & isec) ;
1545+ }
1546+ t
1547+ }
1548+ ( other, Refinement ( refine) ) | ( Refinement ( refine) , other) => {
1549+ let other = other. clone ( ) . into_refinement ( ) ;
1550+ let intersec = self . intersection_refinement ( & other, refine) ;
1551+ self . try_squash_refinement ( intersec)
1552+ . unwrap_or_else ( Type :: Refinement )
1553+ }
15301554 // overloading
15311555 ( l, r) if l. is_subr ( ) && r. is_subr ( ) => and ( lhs. clone ( ) , rhs. clone ( ) ) ,
15321556 _ => self . simple_intersection ( lhs, rhs) ,
0 commit comments