@@ -1282,6 +1282,7 @@ impl Context {
1282
1282
/// union(Array(Int, 2), Array(Str, 3)) == Array(Int, 2) or Array(Int, 3)
1283
1283
/// union({ .a = Int }, { .a = Str }) == { .a = Int or Str }
1284
1284
/// union({ .a = Int }, { .a = Int; .b = Int }) == { .a = Int }
1285
+ /// union((A and B) or C) == (A or C) and (B or C)
1285
1286
/// ```
1286
1287
pub ( crate ) fn union ( & self , lhs : & Type , rhs : & Type ) -> Type {
1287
1288
if lhs == rhs {
@@ -1345,6 +1346,16 @@ impl Context {
1345
1346
_ => self . simple_union ( lhs, rhs) ,
1346
1347
} ,
1347
1348
( 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
+ }
1348
1359
( t, Type :: Never ) | ( Type :: Never , t) => t. clone ( ) ,
1349
1360
// Array({1, 2}, 2), Array({3, 4}, 2) ==> Array({1, 2, 3, 4}, 2)
1350
1361
(
@@ -1497,12 +1508,6 @@ impl Context {
1497
1508
self . intersection ( & fv. crack ( ) , other)
1498
1509
}
1499
1510
( 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
- }
1506
1511
( Structural ( l) , Structural ( r) ) => self . intersection ( l, r) . structuralize ( ) ,
1507
1512
( Guard ( l) , Guard ( r) ) => {
1508
1513
if l. namespace == r. namespace && l. target == r. target {
@@ -1527,6 +1532,26 @@ impl Context {
1527
1532
( other, and @ And ( _, _) ) | ( and @ And ( _, _) , other) => {
1528
1533
self . intersection_add ( and, other)
1529
1534
}
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
+ let mut t = Type :: Never ;
1539
+ for branch in ors. iter ( ) {
1540
+ let isec = self . intersection ( branch, other) ;
1541
+ if branch. is_unbound_var ( ) {
1542
+ t = or ( t, isec) ;
1543
+ } else {
1544
+ t = self . union ( & t, & isec) ;
1545
+ }
1546
+ }
1547
+ t
1548
+ }
1549
+ ( other, Refinement ( refine) ) | ( Refinement ( refine) , other) => {
1550
+ let other = other. clone ( ) . into_refinement ( ) ;
1551
+ let intersec = self . intersection_refinement ( & other, refine) ;
1552
+ self . try_squash_refinement ( intersec)
1553
+ . unwrap_or_else ( Type :: Refinement )
1554
+ }
1530
1555
// overloading
1531
1556
( l, r) if l. is_subr ( ) && r. is_subr ( ) => and ( lhs. clone ( ) , rhs. clone ( ) ) ,
1532
1557
_ => self . simple_intersection ( lhs, rhs) ,
0 commit comments