fn join()

in checker/src/abstract_value.rs [3324:3457]


    fn join(&self, other: Rc<AbstractValue>) -> Rc<AbstractValue> {
        // [{} join y] -> y
        if self.is_bottom() {
            return other;
        }
        // [TOP join y] -> TOP
        if self.is_top() {
            return self.clone();
        }
        // [x join {}] -> x
        if other.is_bottom() {
            return self.clone();
        }
        // [x join x] -> x
        if self.eq(&other) {
            return other;
        }
        // [x join TOP] -> TOP
        if other.is_top() {
            return other;
        }
        match (&self.expression, &other.expression) {
            // [(x join y) join (y join z)] -> x join (y join z)
            (
                Expression::Join {
                    left: x, right: y1, ..
                },
                Expression::Join { left: y2, .. },
            ) if y1.eq(y2) => {
                return x.join(other);
            }
            // [(x join y) join (z join a)] -> x join (y join (z join a))
            (
                Expression::Join {
                    left: x, right: y, ..
                },
                Expression::Join { .. },
            ) => {
                return x.join(y.join(other));
            }
            // [x_join_y join widen(x_join_y)] -> widen(x_join_y)
            (Expression::Join { .. }, Expression::WidenedJoin { operand, .. })
                if self.eq(operand) =>
            {
                return other;
            }
            // [(x join y) join y] -> x join y
            // [(x join y) join x] -> x join y
            (Expression::Join { left: x, right: y }, _) if x.eq(&other) || y.eq(&other) => {
                return self.clone();
            }
            // [x join (x join y)] -> x join y
            // [y join (x join y)] -> x join y
            (_, Expression::Join { left: x, right: y }) if x.eq(self) || y.eq(self) => {
                return other;
            }
            // [widen(x_join_y) join x_join_y] -> widen(x_join_y)
            (Expression::WidenedJoin { operand, .. }, Expression::Join { .. })
                if other.eq(operand) =>
            {
                return self.clone();
            }
            // [widen(x, p) join widen(y, p)] -> widen(x, p)
            (
                Expression::WidenedJoin { path: p1, .. },
                Expression::WidenedJoin { path: p2, .. },
            ) if p1.eq(p2) => {
                return self.clone();
            }
            // [widen(x_join_y) join x] -> widen(x_join_y)
            // [widen(x_join_y) join y] -> widen(x_join_y)
            (Expression::WidenedJoin { operand, .. }, _) => {
                if let Expression::Join { left, right } = &operand.expression {
                    if left.eq(&other) || right.eq(&other) {
                        return self.clone();
                    }
                }
            }
            // [x join (if c { x } else { y })] -> x join y
            // [x join (if c { y } else { x })] -> x join y
            (
                _,
                Expression::ConditionalExpression {
                    consequent: x,
                    alternate: y,
                    ..
                },
            )
            | (
                _,
                Expression::ConditionalExpression {
                    consequent: y,
                    alternate: x,
                    ..
                },
            ) if self.eq(x) => {
                return x.join(y.clone());
            }
            // [x join (y join (x join z))] -> x join (y join z)
            (
                _,
                Expression::Join {
                    left: y, right: xz, ..
                },
            ) if matches!(&xz.expression, Expression::Join { .. }) => {
                if let Expression::Join {
                    left: x, right: z, ..
                } = &xz.expression
                {
                    if self.eq(x) {
                        return self.join(y.join(z.clone()));
                    }
                }
            }
            // [x join widened(x join y)] -> widened(x join y)
            // [y join widened(x join y)] -> widened(x join y)
            (_, Expression::WidenedJoin { operand, .. }) => {
                if let Expression::Join { left: x, right: y } = &operand.expression {
                    if self.eq(x) || self.eq(y) {
                        return other.clone();
                    }
                }
            }
            _ => {}
        }
        let expression_size = self.expression_size.saturating_add(other.expression_size);
        AbstractValue::make_from(
            Expression::Join {
                left: self.clone(),
                right: other,
            },
            expression_size,
        )
    }