/// walking upward while evaluation keeps simplifying parents. This exploits the semantic property
/// that local constant and partial evaluation is always preferable to trying lower-priority rules,
/// the symbol table, or recursively inspect arbitrary descendants. Children are expected to have
/// At [`Expr::Root`], a selective deep pass runs over top-level constraints (skipping solver-flat
/// re-traversed. Local root-list reshaping (flatten top-level `and`) is intentionally deferred to
/// Applies local root-list partial evaluation (strip `true`, propagate `false`, flatten `and`s).
/// Callers that know which root child changed should prefer this over rebuilding the whole root:
Expr::AbstractLiteral(_, lit) => abstract_literal_children_are_locally_evaluable(lit),
Expr::AbstractLiteral(_, lit) => abstract_literal_children_are_locally_evaluable(lit),
fn abstract_literal_children_are_locally_evaluable(lit: &AbstractLiteral<Expr>) -> bool {
/// `None` if the expression cannot be simplified to a constant (e.g. if it contains a variable)
Expr::Sum(_, exprs) => vec_lit_op::<i32, i32>(|e| e.iter().sum(), exprs).map(Lit::Int),
Expr::LexGt(_, a, b) => eval_constant(&Expr::LexLt(Metadata::new(), b.clone(), a.clone())),
pub(crate) fn generator_values_from_constant_collection(lit: &Lit) -> Option<Vec<Lit>> {
let old_kind = target.replace_kind(DeclarationKind::TemporaryValueLetting(Expr::Atomic(