fn cast()

in checker/src/abstract_value.rs [1875:1969]


    fn cast(&self, target_type: ExpressionType) -> Rc<AbstractValue> {
        match &self.expression {
            Expression::Bottom => self.clone(),
            Expression::ConditionalExpression {
                condition,
                consequent,
                alternate,
            } => condition
                .conditional_expression(consequent.cast(target_type), alternate.cast(target_type)),
            Expression::Join { left, right } => {
                left.cast(target_type).join(right.cast(target_type))
            }
            Expression::Switch {
                discriminator,
                cases,
                default,
            } => discriminator.switch(
                cases
                    .iter()
                    .map(|(case_val, result_val)| (case_val.clone(), result_val.cast(target_type)))
                    .collect(),
                default.cast(target_type),
            ),
            _ => {
                match &self.expression {
                    // [(x as t1) as target_type] -> x as target_type if t1.max_value() >= target_type.max_value()
                    Expression::Cast {
                        operand,
                        target_type: t1,
                    } => {
                        if t1.is_integer()
                            && target_type.is_unsigned_integer()
                            && t1
                                .max_value()
                                .greater_or_equal(&target_type.max_value())
                                .as_bool_if_known()
                                .unwrap_or(false)
                        {
                            return operand.cast(target_type);
                        }
                    }
                    // [(x % c1) as t] -> (x as t) if c1 == t.modulo_value()
                    Expression::Rem { left, right } => {
                        if right
                            .equals(target_type.modulo_value())
                            .as_bool_if_known()
                            .unwrap_or(false)
                        {
                            return left.cast(target_type);
                        }
                    }
                    // [(v : t1) as target_type] -> (v: t1) if t1.max_value() == target_type.max_value()
                    Expression::Variable { var_type: t1, .. }
                    | Expression::InitialParameterValue { var_type: t1, .. } => {
                        if t1.is_integer()
                            && target_type.is_unsigned_integer()
                            && t1
                                .max_value()
                                .equals(&target_type.max_value())
                                .as_bool_if_known()
                                .unwrap_or(false)
                        {
                            return self.clone();
                        }
                    }
                    _ => (),
                }
                let source_type = self.expression.infer_type();
                if source_type != target_type {
                    if source_type == ExpressionType::NonPrimitive
                        && target_type == ExpressionType::ThinPointer
                    {
                        let field0 = Path::new_field(Path::get_as_path(self.clone()), 0);
                        AbstractValue::make_typed_unknown(target_type, field0)
                    } else {
                        self.try_to_constant_fold_and_distribute_typed_unary_op(
                            target_type,
                            ConstantDomain::cast,
                            Self::cast,
                            |o, t| {
                                AbstractValue::make_typed_unary(o, t, |operand, target_type| {
                                    Expression::Cast {
                                        operand,
                                        target_type,
                                    }
                                })
                            },
                        )
                    }
                } else {
                    self.clone()
                }
            }
        }
    }