flux_middle/rty/
expr.rs

1use std::{fmt, iter, ops::ControlFlow, sync::OnceLock};
2
3use flux_arc_interner::{Interned, List, impl_internable, impl_slice_internable};
4use flux_common::bug;
5use flux_macros::{TypeFoldable, TypeVisitable};
6use flux_rustc_bridge::{
7    ToRustc,
8    const_eval::{scalar_to_bits, scalar_to_int, scalar_to_uint},
9    ty::{Const, ConstKind, ValTree, VariantIdx},
10};
11use itertools::Itertools;
12use rustc_abi::{FIRST_VARIANT, FieldIdx};
13use rustc_data_structures::snapshot_map::SnapshotMap;
14use rustc_hir::def_id::DefId;
15use rustc_index::newtype_index;
16use rustc_macros::{Decodable, Encodable, TyDecodable, TyEncodable};
17use rustc_middle::{
18    mir::Local,
19    ty::{ParamConst, ScalarInt, TyCtxt},
20};
21use rustc_span::{Span, Symbol};
22use rustc_type_ir::{BoundVar, DebruijnIndex, INNERMOST};
23
24use super::{
25    BaseTy, Binder, BoundReftKind, BoundVariableKinds, FuncSort, GenericArgs, GenericArgsExt as _,
26    IntTy, Sort, UintTy,
27};
28use crate::{
29    big_int::BigInt,
30    def_id::FluxDefId,
31    fhir::{self},
32    global_env::GlobalEnv,
33    pretty::*,
34    queries::QueryResult,
35    rty::{
36        BoundVariableKind, SortArg,
37        fold::{
38            TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable as _,
39            TypeVisitor,
40        },
41    },
42};
43
44/// A lambda abstraction with an elaborated output sort. We need the output sort of lambdas for
45/// encoding into fixpoint
46#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
47pub struct Lambda {
48    body: Binder<Expr>,
49    output: Sort,
50}
51
52impl Lambda {
53    pub fn bind_with_vars(body: Expr, inputs: BoundVariableKinds, output: Sort) -> Self {
54        debug_assert!(inputs.iter().all(BoundVariableKind::is_refine));
55        Self { body: Binder::bind_with_vars(body, inputs), output }
56    }
57
58    pub fn bind_with_fsort(body: Expr, fsort: FuncSort) -> Self {
59        Self { body: Binder::bind_with_sorts(body, fsort.inputs()), output: fsort.output().clone() }
60    }
61
62    pub fn apply(&self, args: &[Expr]) -> Expr {
63        self.body.replace_bound_refts(args)
64    }
65
66    pub fn vars(&self) -> &BoundVariableKinds {
67        self.body.vars()
68    }
69
70    pub fn output(&self) -> Sort {
71        self.output.clone()
72    }
73
74    pub fn fsort(&self) -> FuncSort {
75        let inputs_and_output = self
76            .vars()
77            .iter()
78            .map(|kind| kind.expect_sort().clone())
79            .chain(iter::once(self.output()))
80            .collect();
81        FuncSort { inputs_and_output }
82    }
83}
84
85#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
86pub struct AliasReft {
87    /// Id of the associated refinement in the trait
88    pub assoc_id: FluxDefId,
89    pub args: GenericArgs,
90}
91
92impl AliasReft {
93    pub fn to_rustc_trait_ref<'tcx>(&self, tcx: TyCtxt<'tcx>) -> rustc_middle::ty::TraitRef<'tcx> {
94        let trait_def_id = self.assoc_id.parent();
95        let args = self
96            .args
97            .to_rustc(tcx)
98            .truncate_to(tcx, tcx.generics_of(trait_def_id));
99        rustc_middle::ty::TraitRef::new(tcx, trait_def_id, args)
100    }
101}
102
103#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
104pub struct Expr {
105    kind: Interned<ExprKind>,
106    espan: Option<ESpan>,
107}
108
109impl Expr {
110    pub fn at_opt(self, espan: Option<ESpan>) -> Expr {
111        Expr { kind: self.kind, espan }
112    }
113
114    pub fn at(self, espan: ESpan) -> Expr {
115        self.at_opt(Some(espan))
116    }
117
118    pub fn at_base(self, base: ESpan) -> Expr {
119        if let Some(espan) = self.espan { self.at(espan.with_base(base)) } else { self }
120    }
121
122    pub fn span(&self) -> Option<ESpan> {
123        self.espan
124    }
125
126    pub fn tt() -> Expr {
127        static TRUE: OnceLock<Expr> = OnceLock::new();
128        TRUE.get_or_init(|| ExprKind::Constant(Constant::Bool(true)).intern())
129            .clone()
130    }
131
132    pub fn ff() -> Expr {
133        static FALSE: OnceLock<Expr> = OnceLock::new();
134        FALSE
135            .get_or_init(|| ExprKind::Constant(Constant::Bool(false)).intern())
136            .clone()
137    }
138
139    pub fn and_from_iter(exprs: impl IntoIterator<Item = Expr>) -> Expr {
140        exprs
141            .into_iter()
142            .reduce(|acc, e| Expr::binary_op(BinOp::And, acc, e))
143            .unwrap_or_else(Expr::tt)
144    }
145
146    pub fn or_from_iter(exprs: impl IntoIterator<Item = Expr>) -> Expr {
147        exprs
148            .into_iter()
149            .reduce(|acc, e| Expr::binary_op(BinOp::Or, acc, e))
150            .unwrap_or_else(Expr::ff)
151    }
152
153    pub fn and(e1: impl Into<Expr>, e2: impl Into<Expr>) -> Expr {
154        Expr::and_from_iter([e1.into(), e2.into()])
155    }
156
157    pub fn or(e1: impl Into<Expr>, e2: impl Into<Expr>) -> Expr {
158        Expr::or_from_iter([e1.into(), e2.into()])
159    }
160
161    pub fn zero() -> Expr {
162        static ZERO: OnceLock<Expr> = OnceLock::new();
163        ZERO.get_or_init(|| ExprKind::Constant(Constant::ZERO).intern())
164            .clone()
165    }
166
167    pub fn int_max(int_ty: IntTy) -> Expr {
168        let bit_width: u64 = int_ty
169            .bit_width()
170            .unwrap_or(flux_config::pointer_width().bits());
171        Expr::constant(Constant::int_max(bit_width.try_into().unwrap()))
172    }
173
174    pub fn int_min(int_ty: IntTy) -> Expr {
175        let bit_width: u64 = int_ty
176            .bit_width()
177            .unwrap_or(flux_config::pointer_width().bits());
178        Expr::constant(Constant::int_min(bit_width.try_into().unwrap()))
179    }
180
181    pub fn uint_max(uint_ty: UintTy) -> Expr {
182        let bit_width: u64 = uint_ty
183            .bit_width()
184            .unwrap_or(flux_config::pointer_width().bits());
185        Expr::constant(Constant::uint_max(bit_width.try_into().unwrap()))
186    }
187
188    pub fn nu() -> Expr {
189        Expr::bvar(INNERMOST, BoundVar::ZERO, BoundReftKind::Anon)
190    }
191
192    pub fn is_nu(&self) -> bool {
193        if let ExprKind::Var(Var::Bound(INNERMOST, var)) = self.kind()
194            && var.var == BoundVar::ZERO
195        {
196            true
197        } else {
198            false
199        }
200    }
201
202    pub fn unit() -> Expr {
203        Expr::tuple(List::empty())
204    }
205
206    pub fn var(var: Var) -> Expr {
207        ExprKind::Var(var).intern()
208    }
209
210    pub fn fvar(name: Name) -> Expr {
211        Var::Free(name).to_expr()
212    }
213
214    pub fn evar(evid: EVid) -> Expr {
215        Var::EVar(evid).to_expr()
216    }
217
218    pub fn bvar(debruijn: DebruijnIndex, var: BoundVar, kind: BoundReftKind) -> Expr {
219        Var::Bound(debruijn, BoundReft { var, kind }).to_expr()
220    }
221
222    pub fn early_param(index: u32, name: Symbol) -> Expr {
223        Var::EarlyParam(EarlyReftParam { index, name }).to_expr()
224    }
225
226    pub fn local(local: Local) -> Expr {
227        ExprKind::Local(local).intern()
228    }
229
230    pub fn constant(c: Constant) -> Expr {
231        ExprKind::Constant(c).intern()
232    }
233
234    pub fn const_def_id(c: DefId) -> Expr {
235        ExprKind::ConstDefId(c).intern()
236    }
237
238    pub fn const_generic(param: ParamConst) -> Expr {
239        ExprKind::Var(Var::ConstGeneric(param)).intern()
240    }
241
242    pub fn tuple(flds: List<Expr>) -> Expr {
243        ExprKind::Tuple(flds).intern()
244    }
245
246    pub fn ctor_struct(def_id: DefId, flds: List<Expr>) -> Expr {
247        ExprKind::Ctor(Ctor::Struct(def_id), flds).intern()
248    }
249
250    pub fn ctor_enum(def_id: DefId, idx: VariantIdx) -> Expr {
251        ExprKind::Ctor(Ctor::Enum(def_id, idx), List::empty()).intern()
252    }
253
254    pub fn ctor(ctor: Ctor, flds: List<Expr>) -> Expr {
255        ExprKind::Ctor(ctor, flds).intern()
256    }
257
258    pub fn is_ctor(def_id: DefId, variant_idx: VariantIdx, idx: impl Into<Expr>) -> Expr {
259        ExprKind::IsCtor(def_id, variant_idx, idx.into()).intern()
260    }
261
262    pub fn from_bits(bty: &BaseTy, bits: u128) -> Expr {
263        // FIXME: We are assuming the higher bits are not set. check this assumption
264        match bty {
265            BaseTy::Int(_) => {
266                let bits = bits as i128;
267                ExprKind::Constant(Constant::from(bits)).intern()
268            }
269            BaseTy::Uint(_) => ExprKind::Constant(Constant::from(bits)).intern(),
270            BaseTy::Bool => ExprKind::Constant(Constant::Bool(bits != 0)).intern(),
271            BaseTy::Char => {
272                let c = char::from_u32(bits.try_into().unwrap()).unwrap();
273                ExprKind::Constant(Constant::Char(c)).intern()
274            }
275            _ => bug!(),
276        }
277    }
278
279    pub fn ite(p: impl Into<Expr>, e1: impl Into<Expr>, e2: impl Into<Expr>) -> Expr {
280        ExprKind::IfThenElse(p.into(), e1.into(), e2.into()).intern()
281    }
282
283    pub fn abs(lam: Lambda) -> Expr {
284        ExprKind::Abs(lam).intern()
285    }
286
287    pub fn let_(init: Expr, body: Binder<Expr>) -> Expr {
288        ExprKind::Let(init, body).intern()
289    }
290
291    pub fn bounded_quant(kind: fhir::QuantKind, rng: fhir::Range, body: Binder<Expr>) -> Expr {
292        ExprKind::BoundedQuant(kind, rng, body).intern()
293    }
294
295    pub fn hole(kind: HoleKind) -> Expr {
296        ExprKind::Hole(kind).intern()
297    }
298
299    pub fn kvar(kvar: KVar) -> Expr {
300        ExprKind::KVar(kvar).intern()
301    }
302
303    pub fn alias(alias: AliasReft, args: List<Expr>) -> Expr {
304        ExprKind::Alias(alias, args).intern()
305    }
306
307    pub fn forall(expr: Binder<Expr>) -> Expr {
308        ExprKind::ForAll(expr).intern()
309    }
310
311    pub fn exists(expr: Binder<Expr>) -> Expr {
312        ExprKind::Exists(expr).intern()
313    }
314
315    pub fn binary_op(op: BinOp, e1: impl Into<Expr>, e2: impl Into<Expr>) -> Expr {
316        ExprKind::BinaryOp(op, e1.into(), e2.into()).intern()
317    }
318
319    pub fn prim_val(op: BinOp, e1: impl Into<Expr>, e2: impl Into<Expr>) -> Expr {
320        Expr::app(InternalFuncKind::Val(op), List::empty(), List::from_arr([e1.into(), e2.into()]))
321    }
322
323    pub fn prim_rel(op: BinOp, e1: impl Into<Expr>, e2: impl Into<Expr>) -> Expr {
324        Expr::app(InternalFuncKind::Rel(op), List::empty(), List::from_arr([e1.into(), e2.into()]))
325    }
326
327    pub fn unit_struct(def_id: DefId) -> Expr {
328        Expr::ctor_struct(def_id, List::empty())
329    }
330
331    pub fn cast(from: Sort, to: Sort, idx: Expr) -> Expr {
332        Expr::app(
333            InternalFuncKind::Cast,
334            List::from_arr([SortArg::Sort(from), SortArg::Sort(to)]),
335            List::from_arr([idx]),
336        )
337    }
338
339    pub fn app(func: impl Into<Expr>, sort_args: List<SortArg>, args: List<Expr>) -> Expr {
340        ExprKind::App(func.into(), sort_args, args).intern()
341    }
342
343    pub fn global_func(kind: SpecFuncKind) -> Expr {
344        ExprKind::GlobalFunc(kind).intern()
345    }
346
347    pub fn internal_func(kind: InternalFuncKind) -> Expr {
348        ExprKind::InternalFunc(kind).intern()
349    }
350
351    pub fn eq(e1: impl Into<Expr>, e2: impl Into<Expr>) -> Expr {
352        ExprKind::BinaryOp(BinOp::Eq, e1.into(), e2.into()).intern()
353    }
354
355    pub fn unary_op(op: UnOp, e: impl Into<Expr>) -> Expr {
356        ExprKind::UnaryOp(op, e.into()).intern()
357    }
358
359    pub fn ne(e1: impl Into<Expr>, e2: impl Into<Expr>) -> Expr {
360        ExprKind::BinaryOp(BinOp::Ne, e1.into(), e2.into()).intern()
361    }
362
363    pub fn ge(e1: impl Into<Expr>, e2: impl Into<Expr>) -> Expr {
364        ExprKind::BinaryOp(BinOp::Ge(Sort::Int), e1.into(), e2.into()).intern()
365    }
366
367    pub fn gt(e1: impl Into<Expr>, e2: impl Into<Expr>) -> Expr {
368        ExprKind::BinaryOp(BinOp::Gt(Sort::Int), e1.into(), e2.into()).intern()
369    }
370
371    pub fn lt(e1: impl Into<Expr>, e2: impl Into<Expr>) -> Expr {
372        ExprKind::BinaryOp(BinOp::Lt(Sort::Int), e1.into(), e2.into()).intern()
373    }
374
375    pub fn le(e1: impl Into<Expr>, e2: impl Into<Expr>) -> Expr {
376        ExprKind::BinaryOp(BinOp::Le(Sort::Int), e1.into(), e2.into()).intern()
377    }
378
379    pub fn implies(e1: impl Into<Expr>, e2: impl Into<Expr>) -> Expr {
380        ExprKind::BinaryOp(BinOp::Imp, e1.into(), e2.into()).intern()
381    }
382
383    pub fn field_proj(e: impl Into<Expr>, proj: FieldProj) -> Expr {
384        ExprKind::FieldProj(e.into(), proj).intern()
385    }
386
387    pub fn field_projs(e: impl Into<Expr>, projs: &[FieldProj]) -> Expr {
388        projs.iter().copied().fold(e.into(), Expr::field_proj)
389    }
390
391    pub fn path_proj(base: Expr, field: FieldIdx) -> Expr {
392        ExprKind::PathProj(base, field).intern()
393    }
394
395    pub fn not(&self) -> Expr {
396        ExprKind::UnaryOp(UnOp::Not, self.clone()).intern()
397    }
398
399    pub fn neg(&self) -> Expr {
400        ExprKind::UnaryOp(UnOp::Neg, self.clone()).intern()
401    }
402
403    pub fn kind(&self) -> &ExprKind {
404        &self.kind
405    }
406
407    /// An expression is an *atom* if it is "self-delimiting", i.e., it has a clear boundary
408    /// when printed. This is used to avoid unnecessary parenthesis when pretty printing.
409    pub fn is_atom(&self) -> bool {
410        !matches!(self.kind(), ExprKind::Abs(..) | ExprKind::BinaryOp(..) | ExprKind::ForAll(..))
411    }
412
413    /// Simple syntactic check to see if the expression is a trivially true predicate. This is used
414    /// mostly for filtering predicates when pretty printing but also to simplify types in general.
415    pub fn is_trivially_true(&self) -> bool {
416        self.is_true()
417            || matches!(self.kind(), ExprKind::BinaryOp(BinOp::Eq | BinOp::Iff | BinOp::Imp, e1, e2) if e1.erase_spans() == e2.erase_spans())
418    }
419
420    /// Simple syntactic check to see if the expression is a trivially false predicate.
421    pub fn is_trivially_false(&self) -> bool {
422        self.is_false()
423    }
424
425    /// Whether the expression is *literally* the constant `true`.
426    fn is_true(&self) -> bool {
427        matches!(self.kind(), ExprKind::Constant(Constant::Bool(true)))
428    }
429
430    /// Whether the expression is *literally* the constant `false`.
431    fn is_false(&self) -> bool {
432        matches!(self.kind(), ExprKind::Constant(Constant::Bool(false)))
433    }
434
435    pub fn from_const(tcx: TyCtxt, c: &Const) -> Expr {
436        match &c.kind {
437            ConstKind::Param(param_const) => Expr::const_generic(*param_const),
438            ConstKind::Value(ty, ValTree::Leaf(scalar)) => {
439                Expr::constant(Constant::from_scalar_int(tcx, *scalar, ty).unwrap())
440            }
441            ConstKind::Value(_ty, ValTree::Branch(_)) => {
442                bug!("todo: ValTree::Branch {c:?}")
443            }
444            // We should have normalized away the unevaluated constants
445            ConstKind::Unevaluated(_) => bug!("unexpected `ConstKind::Unevaluated`"),
446
447            ConstKind::Infer(_) => bug!("unexpected `ConstKind::Infer`"),
448        }
449    }
450
451    fn const_op(op: &BinOp, c1: &Constant, c2: &Constant) -> Option<Constant> {
452        match op {
453            BinOp::Iff => c1.iff(c2),
454            BinOp::Imp => c1.imp(c2),
455            BinOp::Or => c1.or(c2),
456            BinOp::And => c1.and(c2),
457            BinOp::Gt(Sort::Int) => c1.gt(c2),
458            BinOp::Ge(Sort::Int) => c1.ge(c2),
459            BinOp::Lt(Sort::Int) => c2.gt(c1),
460            BinOp::Le(Sort::Int) => c2.ge(c1),
461            BinOp::Eq => Some(c1.eq(c2)),
462            BinOp::Ne => Some(c1.ne(c2)),
463            _ => None,
464        }
465    }
466
467    /// Simplify the expression by removing double negations, short-circuiting boolean connectives and
468    /// doing constant folding. Note that we also have [`TypeFoldable::normalize`] which applies beta
469    /// reductions for tuples and abstractions.
470    ///
471    /// Additionally replaces any occurrences of elements in assumed_preds with True.
472    pub fn simplify(&self, assumed_preds: &SnapshotMap<Expr, ()>) -> Expr {
473        struct Simplify<'a> {
474            assumed_preds: &'a SnapshotMap<Expr, ()>,
475        }
476
477        impl TypeFolder for Simplify<'_> {
478            fn fold_expr(&mut self, expr: &Expr) -> Expr {
479                if self.assumed_preds.get(&expr.erase_spans()).is_some() {
480                    return Expr::tt();
481                }
482                let span = expr.span();
483                match expr.kind() {
484                    ExprKind::BinaryOp(op, e1, e2) => {
485                        let e1 = e1.fold_with(self);
486                        let e2 = e2.fold_with(self);
487                        match (op, e1.kind(), e2.kind()) {
488                            (BinOp::And, ExprKind::Constant(Constant::Bool(false)), _) => {
489                                Expr::constant(Constant::Bool(false)).at_opt(e1.span())
490                            }
491                            (BinOp::And, _, ExprKind::Constant(Constant::Bool(false))) => {
492                                Expr::constant(Constant::Bool(false)).at_opt(e2.span())
493                            }
494                            (BinOp::And, ExprKind::Constant(Constant::Bool(true)), _) => e2,
495                            (BinOp::And, _, ExprKind::Constant(Constant::Bool(true))) => e1,
496                            (op, ExprKind::Constant(c1), ExprKind::Constant(c2)) => {
497                                if let Some(c) = Expr::const_op(op, c1, c2) {
498                                    Expr::constant(c).at_opt(span.or(e2.span()))
499                                } else {
500                                    Expr::binary_op(op.clone(), e1, e2).at_opt(span)
501                                }
502                            }
503                            _ => Expr::binary_op(op.clone(), e1, e2).at_opt(span),
504                        }
505                    }
506                    ExprKind::UnaryOp(UnOp::Not, e) => {
507                        let e = e.fold_with(self);
508                        match e.kind() {
509                            ExprKind::Constant(Constant::Bool(b)) => {
510                                Expr::constant(Constant::Bool(!b))
511                            }
512                            ExprKind::UnaryOp(UnOp::Not, e) => e.clone(),
513                            ExprKind::BinaryOp(BinOp::Eq, e1, e2) => {
514                                Expr::binary_op(BinOp::Ne, e1, e2).at_opt(span)
515                            }
516                            _ => Expr::unary_op(UnOp::Not, e).at_opt(span),
517                        }
518                    }
519                    ExprKind::IfThenElse(p, e1, e2) => {
520                        let p = p.fold_with(self);
521                        if p.is_trivially_true() {
522                            e1.fold_with(self).at_opt(span)
523                        } else if p.is_trivially_false() {
524                            e2.fold_with(self).at_opt(span)
525                        } else {
526                            Expr::ite(p, e1.fold_with(self), e2.fold_with(self)).at_opt(span)
527                        }
528                    }
529                    _ => expr.super_fold_with(self),
530                }
531            }
532        }
533        self.fold_with(&mut Simplify { assumed_preds })
534    }
535
536    pub fn to_loc(&self) -> Option<Loc> {
537        match self.kind() {
538            ExprKind::Local(local) => Some(Loc::Local(*local)),
539            ExprKind::Var(var) => Some(Loc::Var(*var)),
540            _ => None,
541        }
542    }
543
544    pub fn to_path(&self) -> Option<Path> {
545        let mut expr = self;
546        let mut proj = vec![];
547        while let ExprKind::PathProj(e, field) = expr.kind() {
548            proj.push(*field);
549            expr = e;
550        }
551        proj.reverse();
552        Some(Path::new(expr.to_loc()?, proj))
553    }
554
555    /// Whether this is an aggregate expression with no fields.
556    pub fn is_unit(&self) -> bool {
557        matches!(self.kind(), ExprKind::Tuple(flds) if flds.is_empty())
558            || matches!(self.kind(), ExprKind::Ctor(Ctor::Struct(_), flds) if flds.is_empty())
559    }
560
561    pub fn eta_expand_abs(&self, inputs: &BoundVariableKinds, output: Sort) -> Lambda {
562        let args = (0..inputs.len())
563            .map(|idx| Expr::bvar(INNERMOST, BoundVar::from_usize(idx), BoundReftKind::Anon))
564            .collect();
565        let body = Expr::app(self, List::empty(), args);
566        Lambda::bind_with_vars(body, inputs.clone(), output)
567    }
568
569    /// Applies a field projection to an expression and optimistically try to beta reduce it
570    pub fn proj_and_reduce(&self, proj: FieldProj) -> Expr {
571        match self.kind() {
572            ExprKind::Tuple(flds) | ExprKind::Ctor(Ctor::Struct(_), flds) => {
573                flds[proj.field_idx() as usize].clone()
574            }
575            _ => Expr::field_proj(self.clone(), proj),
576        }
577    }
578
579    pub fn visit_conj<'a>(&'a self, mut f: impl FnMut(&'a Expr)) {
580        fn go<'a>(e: &'a Expr, f: &mut impl FnMut(&'a Expr)) {
581            if let ExprKind::BinaryOp(BinOp::And, e1, e2) = e.kind() {
582                go(e1, f);
583                go(e2, f);
584            } else {
585                f(e);
586            }
587        }
588        go(self, &mut f);
589    }
590
591    pub fn flatten_conjs(&self) -> Vec<&Expr> {
592        let mut vec = vec![];
593        self.visit_conj(|e| vec.push(e));
594        vec
595    }
596
597    pub fn has_evars(&self) -> bool {
598        struct HasEvars;
599
600        impl TypeVisitor for HasEvars {
601            type BreakTy = ();
602            fn visit_expr(&mut self, expr: &Expr) -> ControlFlow<Self::BreakTy> {
603                if let ExprKind::Var(Var::EVar(_)) = expr.kind() {
604                    ControlFlow::Break(())
605                } else {
606                    expr.super_visit_with(self)
607                }
608            }
609        }
610
611        self.visit_with(&mut HasEvars).is_break()
612    }
613
614    pub fn erase_spans(&self) -> Expr {
615        struct SpanEraser;
616        impl TypeFolder for SpanEraser {
617            fn fold_expr(&mut self, e: &Expr) -> Expr {
618                e.super_fold_with(self).at_opt(None)
619            }
620        }
621        self.fold_with(&mut SpanEraser)
622    }
623}
624
625#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug)]
626pub struct ESpan {
627    /// The top-level span information
628    pub span: Span,
629    /// The span for the (base) call-site for def-expanded spans
630    pub base: Option<Span>,
631}
632
633impl ESpan {
634    pub fn new(span: Span) -> Self {
635        Self { span, base: None }
636    }
637
638    pub fn with_base(&self, espan: ESpan) -> Self {
639        Self { span: self.span, base: Some(espan.span) }
640    }
641}
642
643#[derive(
644    Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, TypeFoldable, TypeVisitable,
645)]
646pub enum BinOp {
647    Iff,
648    Imp,
649    Or,
650    And,
651    Eq,
652    Ne,
653    Gt(Sort),
654    Ge(Sort),
655    Lt(Sort),
656    Le(Sort),
657    Add(Sort),
658    Sub(Sort),
659    Mul(Sort),
660    Div(Sort),
661    Mod(Sort),
662    BitAnd,
663    BitOr,
664    BitXor,
665    BitShl,
666    BitShr,
667}
668
669#[derive(Clone, Copy, PartialEq, Eq, Hash, Encodable, Debug, Decodable)]
670pub enum UnOp {
671    Not,
672    Neg,
673}
674
675#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, TyEncodable, TyDecodable)]
676pub enum Ctor {
677    /// for indices represented as `struct` in the refinement logic (e.g. using `refined_by` annotations)
678    Struct(DefId),
679    /// for indices represented as  `enum` in the refinement logic (e.g. using `reflected` annotations)
680    Enum(DefId, VariantIdx),
681}
682
683impl Ctor {
684    pub fn def_id(&self) -> DefId {
685        match self {
686            Self::Struct(def_id) | Self::Enum(def_id, _) => *def_id,
687        }
688    }
689
690    pub fn variant_idx(&self) -> VariantIdx {
691        match self {
692            Self::Struct(_) => FIRST_VARIANT,
693            Self::Enum(_, variant_idx) => *variant_idx,
694        }
695    }
696
697    fn is_enum(&self) -> bool {
698        matches!(self, Self::Enum(..))
699    }
700}
701
702/// # Primitive Properties
703/// Given a primop `op` with signature `(t1,...,tn) -> t`
704/// We define a refined type for `op` expressed as a `RuleMatcher`
705///
706/// ```text
707/// op :: (x1: t1, ..., xn: tn) -> { t[op_val[op](x1,...,xn)] | op_rel[x1,...,xn] }
708/// ```
709/// That is, using two *uninterpreted functions* `op_val` and `op_rel` that respectively denote
710/// 1. The _value_ of the primop, and
711/// 2. Some invariant _relation_ that holds for the primop.
712///
713/// The latter can be extended by the user via a `property` definition, which allows us
714/// to customize primops like `<<` with extra "facts" or lemmas. See `tests/tests/pos/surface/primops00.rs` for an example.
715#[derive(Debug, Clone, TyEncodable, TyDecodable, PartialEq, Eq, Hash)]
716pub enum InternalFuncKind {
717    /// UIF representing the value of a primop
718    Val(BinOp),
719    /// UIF representing the relationship of a primop
720    Rel(BinOp),
721    // Conversions betweeen Sorts
722    Cast,
723}
724
725#[derive(Debug, Clone, TyEncodable, TyDecodable, PartialEq, Eq, Hash)]
726pub enum SpecFuncKind {
727    /// Theory symbols *interpreted* by the SMT solver
728    Thy(liquid_fixpoint::ThyFunc),
729    /// User-defined uninterpreted functions with no definition
730    Uif(FluxDefId),
731    /// User-defined functions with a body definition
732    Def(FluxDefId),
733}
734
735#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, Debug, TyDecodable)]
736pub enum ExprKind {
737    Var(Var),
738    Local(Local),
739    Constant(Constant),
740    /// A rust constant. This can be either `DefKind::Const` or `DefKind::AssocConst`
741    ConstDefId(DefId),
742    BinaryOp(BinOp, Expr, Expr),
743    GlobalFunc(SpecFuncKind),
744    InternalFunc(InternalFuncKind),
745    UnaryOp(UnOp, Expr),
746    FieldProj(Expr, FieldProj),
747    /// A variant used in the logic to represent a variant of an ADT as a pair of the `DefId` and variant-index
748    Ctor(Ctor, List<Expr>),
749    Tuple(List<Expr>),
750    PathProj(Expr, FieldIdx),
751    IfThenElse(Expr, Expr, Expr),
752    KVar(KVar),
753    Alias(AliasReft, List<Expr>),
754    Let(Expr, Binder<Expr>),
755    /// Function application. The syntax allows arbitrary expressions in function position, but in
756    /// practice we are restricted by what's possible to encode in fixpoint. In a nutshell, we need
757    /// to make sure that expressions that can't be encoded are eliminated before we generate the
758    /// fixpoint constraint. Most notably, lambda abstractions have to be fully applied before
759    /// encoding into fixpoint (except when they appear as an index at the top-level).
760    App(Expr, List<SortArg>, List<Expr>),
761    /// Lambda abstractions. They are purely syntactic and we don't encode them in the logic. As such,
762    /// they have some syntactic restrictions that we must carefully maintain:
763    ///
764    /// 1. They can appear as an index at the top level.
765    /// 2. We can only substitute an abstraction for a variable in function position (or as an index).
766    ///    More generally, we need to partially evaluate expressions such that all abstractions in
767    ///    non-index position are eliminated before encoding into fixpoint. Right now, the
768    ///    implementation only evaluates abstractions that are immediately applied to arguments,
769    ///    thus the restriction.
770    Abs(Lambda),
771
772    /// Bounded quantifiers `exists i in 0..4 { pred(i) }` and `forall i in 0..4 { pred(i) }`.
773    BoundedQuant(fhir::QuantKind, fhir::Range, Binder<Expr>),
774    /// A hole is an expression that must be inferred either *semantically* by generating a kvar or
775    /// *syntactically* by generating an evar. Whether a hole can be inferred semantically or
776    /// syntactically depends on the position it appears: only holes appearing in predicate position
777    /// can be inferred with a kvar (provided it satisfies the fixpoint horn constraints) and only
778    /// holes used as an index (a position that fully determines their value) can be inferred with
779    /// an evar.
780    ///
781    /// Holes are implicitly defined in a scope, i.e., their solution could mention free and bound
782    /// variables in this scope. This must be considered when generating an inference variables for
783    /// them (either evar or kvar). In fact, the main reason we have holes is that we want to
784    /// decouple the places where we generate holes (where we don't want to worry about the scope),
785    /// and the places where we generate inference variable for them (where we do need to worry
786    /// about the scope).
787    Hole(HoleKind),
788    ForAll(Binder<Expr>),
789    /// Only for non-cuts solutions from fixpoint
790    Exists(Binder<Expr>),
791    /// Is the expression constructed from constructor of the given DefId (which should be `reflected` Enum)
792    IsCtor(DefId, VariantIdx, Expr),
793}
794
795impl ExprKind {
796    fn intern(self) -> Expr {
797        Expr { kind: Interned::new(self), espan: None }
798    }
799}
800
801#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug)]
802pub enum AggregateKind {
803    Tuple(usize),
804    Adt(DefId),
805}
806
807#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug)]
808pub enum FieldProj {
809    Tuple { arity: usize, field: u32 },
810    Adt { def_id: DefId, field: u32 },
811}
812
813impl FieldProj {
814    pub fn arity(&self, genv: GlobalEnv) -> QueryResult<usize> {
815        match self {
816            FieldProj::Tuple { arity, .. } => Ok(*arity),
817            FieldProj::Adt { def_id, .. } => {
818                Ok(genv.adt_sort_def_of(*def_id)?.struct_variant().fields())
819            }
820        }
821    }
822
823    pub fn field_idx(&self) -> u32 {
824        match self {
825            FieldProj::Tuple { field, .. } | FieldProj::Adt { field, .. } => *field,
826        }
827    }
828}
829
830/// The position where a [hole] appears. This determines how it will be inferred. This is related
831/// to, but not the same as, an [`InferMode`].
832///
833/// [`InferMode`]: super::InferMode
834/// [hole]: ExprKind::Hole
835#[derive(
836    Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable,
837)]
838pub enum HoleKind {
839    /// A hole in predicate position (e.g., the predicate in a [`TyKind::Constr`]). It will be
840    /// inferred by generating a kvar.
841    ///
842    /// [`TyKind::Constr`]: super::TyKind::Constr
843    Pred,
844    /// A hole used as a refinement argument or index. It will be inferred by generating an evar.
845    /// The expression filling the hole must have the provided sort.
846    ///
847    /// NOTE(nilehmann) we used to require the `Sort` for generating the evar because we needed it
848    /// to eta-expand aggregate sorts. We've since removed this behavior but I'm keeping it here
849    /// just in case. We could remove in case it becomes too problematic.
850    Expr(Sort),
851}
852
853/// In theory a kvar is just an unknown predicate that can use some variables in scope. In practice,
854/// fixpoint makes a difference between the first and the rest of the arguments, the first one being
855/// the kvar's *self argument*. Fixpoint will only instantiate qualifiers that use the self argument.
856/// Flux generalizes the self argument to be a list. We call the rest of the arguments the *scope*.
857#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
858pub struct KVar {
859    pub kvid: KVid,
860    /// The number of arguments consider to be *self arguments*.
861    pub self_args: usize,
862    /// The list of *all* arguments with the self arguments at the beginning, i.e., the
863    /// list of self arguments followed by the scope.
864    pub args: List<Expr>,
865}
866
867#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Encodable, Decodable)]
868pub struct EarlyReftParam {
869    pub index: u32,
870    pub name: Symbol,
871}
872
873#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Encodable, Decodable, Debug)]
874pub struct BoundReft {
875    pub var: BoundVar,
876    pub kind: BoundReftKind,
877}
878
879#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)]
880pub enum Var {
881    Free(Name),
882    Bound(DebruijnIndex, BoundReft),
883    EarlyParam(EarlyReftParam),
884    EVar(EVid),
885    ConstGeneric(ParamConst),
886}
887
888#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)]
889pub struct Path {
890    pub loc: Loc,
891    projection: List<FieldIdx>,
892}
893
894#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)]
895pub enum Loc {
896    Local(Local),
897    Var(Var),
898}
899
900newtype_index! {
901    /// *E*xistential *v*ariable *id*
902    #[debug_format = "?{}e"]
903    #[orderable]
904    #[encodable]
905    pub struct EVid {}
906}
907
908newtype_index! {
909    #[debug_format = "$k{}"]
910    #[encodable]
911    pub struct KVid {}
912}
913
914newtype_index! {
915    #[debug_format = "a{}"]
916    #[orderable]
917    #[encodable]
918    pub struct Name {}
919}
920
921impl KVar {
922    pub fn new(kvid: KVid, self_args: usize, args: Vec<Expr>) -> Self {
923        KVar { kvid, self_args, args: List::from_vec(args) }
924    }
925
926    fn self_args(&self) -> &[Expr] {
927        &self.args[..self.self_args]
928    }
929
930    fn scope(&self) -> &[Expr] {
931        &self.args[self.self_args..]
932    }
933}
934
935impl Var {
936    pub fn to_expr(&self) -> Expr {
937        Expr::var(*self)
938    }
939}
940
941impl Path {
942    pub fn new(loc: Loc, projection: impl Into<List<FieldIdx>>) -> Path {
943        Path { loc, projection: projection.into() }
944    }
945
946    pub fn projection(&self) -> &[FieldIdx] {
947        &self.projection[..]
948    }
949
950    pub fn to_expr(&self) -> Expr {
951        self.projection
952            .iter()
953            .fold(self.loc.to_expr(), |e, f| Expr::path_proj(e, *f))
954    }
955
956    pub fn to_loc(&self) -> Option<Loc> {
957        if self.projection.is_empty() { Some(self.loc) } else { None }
958    }
959}
960
961impl Loc {
962    pub fn to_expr(&self) -> Expr {
963        match self {
964            Loc::Local(local) => Expr::local(*local),
965            Loc::Var(var) => Expr::var(*var),
966        }
967    }
968}
969
970macro_rules! impl_ops {
971    ($($op:ident: $method:ident),*) => {$(
972        impl<Rhs> std::ops::$op<Rhs> for Expr
973        where
974            Rhs: Into<Expr>,
975        {
976            type Output = Expr;
977
978            fn $method(self, rhs: Rhs) -> Self::Output {
979                let sort = crate::rty::Sort::Int;
980                Expr::binary_op(BinOp::$op(sort), self, rhs)
981            }
982        }
983
984        impl<Rhs> std::ops::$op<Rhs> for &Expr
985        where
986            Rhs: Into<Expr>,
987        {
988            type Output = Expr;
989
990            fn $method(self, rhs: Rhs) -> Self::Output {
991                let sort = crate::rty::Sort::Int;
992                Expr::binary_op(BinOp::$op(sort), self, rhs)
993            }
994        }
995    )*};
996}
997impl_ops!(Add: add, Sub: sub, Mul: mul, Div: div);
998
999impl From<i32> for Expr {
1000    fn from(value: i32) -> Self {
1001        Expr::constant(Constant::from(value))
1002    }
1003}
1004
1005impl From<&Expr> for Expr {
1006    fn from(e: &Expr) -> Self {
1007        e.clone()
1008    }
1009}
1010
1011impl From<Path> for Expr {
1012    fn from(path: Path) -> Self {
1013        path.to_expr()
1014    }
1015}
1016
1017impl From<Name> for Expr {
1018    fn from(name: Name) -> Self {
1019        Expr::fvar(name)
1020    }
1021}
1022
1023impl From<Var> for Expr {
1024    fn from(var: Var) -> Self {
1025        Expr::var(var)
1026    }
1027}
1028
1029impl From<SpecFuncKind> for Expr {
1030    fn from(kind: SpecFuncKind) -> Self {
1031        Expr::global_func(kind)
1032    }
1033}
1034
1035impl From<InternalFuncKind> for Expr {
1036    fn from(kind: InternalFuncKind) -> Self {
1037        Expr::internal_func(kind)
1038    }
1039}
1040
1041impl From<Loc> for Path {
1042    fn from(loc: Loc) -> Self {
1043        Path::new(loc, vec![])
1044    }
1045}
1046
1047impl From<Name> for Loc {
1048    fn from(name: Name) -> Self {
1049        Loc::Var(Var::Free(name))
1050    }
1051}
1052
1053impl From<Local> for Loc {
1054    fn from(local: Local) -> Self {
1055        Loc::Local(local)
1056    }
1057}
1058
1059#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable)]
1060pub struct Real(pub u128);
1061
1062#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable)]
1063pub enum Constant {
1064    Int(BigInt),
1065    Real(Real),
1066    Bool(bool),
1067    Str(Symbol),
1068    Char(char),
1069    BitVec(u128, u32),
1070}
1071
1072impl Constant {
1073    pub const ZERO: Constant = Constant::Int(BigInt::ZERO);
1074    pub const ONE: Constant = Constant::Int(BigInt::ONE);
1075    pub const TRUE: Constant = Constant::Bool(true);
1076
1077    fn to_bool(self) -> Option<bool> {
1078        match self {
1079            Constant::Bool(b) => Some(b),
1080            _ => None,
1081        }
1082    }
1083
1084    fn to_int(self) -> Option<BigInt> {
1085        match self {
1086            Constant::Int(n) => Some(n),
1087            _ => None,
1088        }
1089    }
1090
1091    pub fn iff(&self, other: &Constant) -> Option<Constant> {
1092        let b1 = self.to_bool()?;
1093        let b2 = other.to_bool()?;
1094        Some(Constant::Bool(b1 == b2))
1095    }
1096
1097    pub fn imp(&self, other: &Constant) -> Option<Constant> {
1098        let b1 = self.to_bool()?;
1099        let b2 = other.to_bool()?;
1100        Some(Constant::Bool(!b1 || b2))
1101    }
1102
1103    pub fn or(&self, other: &Constant) -> Option<Constant> {
1104        let b1 = self.to_bool()?;
1105        let b2 = other.to_bool()?;
1106        Some(Constant::Bool(b1 || b2))
1107    }
1108
1109    pub fn and(&self, other: &Constant) -> Option<Constant> {
1110        let b1 = self.to_bool()?;
1111        let b2 = other.to_bool()?;
1112        Some(Constant::Bool(b1 && b2))
1113    }
1114
1115    pub fn eq(&self, other: &Constant) -> Constant {
1116        Constant::Bool(*self == *other)
1117    }
1118
1119    pub fn ne(&self, other: &Constant) -> Constant {
1120        Constant::Bool(*self != *other)
1121    }
1122
1123    pub fn gt(&self, other: &Constant) -> Option<Constant> {
1124        let n1 = self.to_int()?;
1125        let n2 = other.to_int()?;
1126        Some(Constant::Bool(n1 > n2))
1127    }
1128
1129    pub fn ge(&self, other: &Constant) -> Option<Constant> {
1130        let n1 = self.to_int()?;
1131        let n2 = other.to_int()?;
1132        Some(Constant::Bool(n1 >= n2))
1133    }
1134
1135    pub fn from_scalar_int<'tcx, T>(tcx: TyCtxt<'tcx>, scalar: ScalarInt, t: &T) -> Option<Self>
1136    where
1137        T: ToRustc<'tcx, T = rustc_middle::ty::Ty<'tcx>>,
1138    {
1139        use rustc_middle::ty::TyKind;
1140        let ty = t.to_rustc(tcx);
1141        match ty.kind() {
1142            TyKind::Int(int_ty) => Some(Constant::from(scalar_to_int(tcx, scalar, *int_ty))),
1143            TyKind::Uint(uint_ty) => Some(Constant::from(scalar_to_uint(tcx, scalar, *uint_ty))),
1144            TyKind::Bool => {
1145                let b = scalar_to_bits(tcx, scalar, ty)?;
1146                Some(Constant::Bool(b != 0))
1147            }
1148            TyKind::Char => {
1149                let b = scalar_to_bits(tcx, scalar, ty)?;
1150                Some(Constant::Char(char::from_u32(b as u32)?))
1151            }
1152            _ => bug!(),
1153        }
1154    }
1155
1156    /// See [`BigInt::int_min`]
1157    pub fn int_min(bit_width: u32) -> Constant {
1158        Constant::Int(BigInt::int_min(bit_width))
1159    }
1160
1161    /// See [`BigInt::int_max`]
1162    pub fn int_max(bit_width: u32) -> Constant {
1163        Constant::Int(BigInt::int_max(bit_width))
1164    }
1165
1166    /// See [`BigInt::uint_max`]
1167    pub fn uint_max(bit_width: u32) -> Constant {
1168        Constant::Int(BigInt::uint_max(bit_width))
1169    }
1170}
1171
1172impl From<i32> for Constant {
1173    fn from(c: i32) -> Self {
1174        Constant::Int(c.into())
1175    }
1176}
1177
1178impl From<usize> for Constant {
1179    fn from(u: usize) -> Self {
1180        Constant::Int(u.into())
1181    }
1182}
1183
1184impl From<u32> for Constant {
1185    fn from(c: u32) -> Self {
1186        Constant::Int(c.into())
1187    }
1188}
1189
1190impl From<u128> for Constant {
1191    fn from(c: u128) -> Self {
1192        Constant::Int(c.into())
1193    }
1194}
1195
1196impl From<i128> for Constant {
1197    fn from(c: i128) -> Self {
1198        Constant::Int(c.into())
1199    }
1200}
1201
1202impl From<bool> for Constant {
1203    fn from(b: bool) -> Self {
1204        Constant::Bool(b)
1205    }
1206}
1207
1208impl From<Symbol> for Constant {
1209    fn from(s: Symbol) -> Self {
1210        Constant::Str(s)
1211    }
1212}
1213
1214impl From<char> for Constant {
1215    fn from(c: char) -> Self {
1216        Constant::Char(c)
1217    }
1218}
1219
1220impl_internable!(ExprKind);
1221impl_slice_internable!(Expr, KVar);
1222
1223#[derive(Debug)]
1224pub struct FieldBind<T> {
1225    pub name: Symbol,
1226    pub value: T,
1227}
1228
1229impl<T: Pretty> Pretty for FieldBind<T> {
1230    fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1231        w!(cx, f, "{}: {:?}", ^self.name, &self.value)
1232    }
1233}
1234
1235pub(crate) mod pretty {
1236    use flux_rustc_bridge::def_id_to_string;
1237
1238    use super::*;
1239    use crate::{name_of_thy_func, rty::pretty::nested_with_bound_vars};
1240
1241    #[derive(PartialEq, Eq, PartialOrd, Ord)]
1242    enum Precedence {
1243        Iff,
1244        Imp,
1245        Or,
1246        And,
1247        Cmp,
1248        Bitvec,
1249        AddSub,
1250        MulDiv,
1251    }
1252
1253    impl BinOp {
1254        fn precedence(&self) -> Precedence {
1255            match self {
1256                BinOp::Iff => Precedence::Iff,
1257                BinOp::Imp => Precedence::Imp,
1258                BinOp::Or => Precedence::Or,
1259                BinOp::And => Precedence::And,
1260                BinOp::Eq
1261                | BinOp::Ne
1262                | BinOp::Gt(_)
1263                | BinOp::Lt(_)
1264                | BinOp::Ge(_)
1265                | BinOp::Le(_) => Precedence::Cmp,
1266                BinOp::Add(_) | BinOp::Sub(_) => Precedence::AddSub,
1267                BinOp::Mul(_) | BinOp::Div(_) | BinOp::Mod(_) => Precedence::MulDiv,
1268                BinOp::BitAnd | BinOp::BitOr | BinOp::BitShl | BinOp::BitShr | BinOp::BitXor => {
1269                    Precedence::Bitvec
1270                }
1271            }
1272        }
1273    }
1274
1275    impl Precedence {
1276        pub fn is_associative(&self) -> bool {
1277            !matches!(self, Precedence::Imp | Precedence::Cmp)
1278        }
1279    }
1280
1281    pub fn should_parenthesize(op: &BinOp, child: &Expr) -> bool {
1282        if let ExprKind::BinaryOp(child_op, ..) = child.kind() {
1283            child_op.precedence() < op.precedence()
1284                || (child_op.precedence() == op.precedence() && !op.precedence().is_associative())
1285        } else {
1286            false
1287        }
1288    }
1289
1290    impl Pretty for Ctor {
1291        fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1292            match self {
1293                Ctor::Struct(def_id) => {
1294                    w!(cx, f, "{:?}", def_id)
1295                }
1296                Ctor::Enum(def_id, variant_idx) => {
1297                    w!(cx, f, "{:?}::{:?}", def_id, ^variant_idx)
1298                }
1299            }
1300        }
1301    }
1302
1303    impl Pretty for fhir::QuantKind {
1304        fn fmt(&self, _cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1305            match self {
1306                fhir::QuantKind::Exists => w!(cx, f, "∃"),
1307                fhir::QuantKind::Forall => w!(cx, f, "∀"),
1308            }
1309        }
1310    }
1311
1312    impl Pretty for InternalFuncKind {
1313        fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1314            match self {
1315                InternalFuncKind::Val(op) => w!(cx, f, "[{:?}]", op),
1316                InternalFuncKind::Rel(op) => w!(cx, f, "[{:?}]?", op),
1317                InternalFuncKind::Cast => w!(cx, f, "cast"),
1318            }
1319        }
1320    }
1321
1322    impl Pretty for Expr {
1323        fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1324            let e = if cx.simplify_exprs {
1325                self.simplify(&SnapshotMap::default())
1326            } else {
1327                self.clone()
1328            };
1329            match e.kind() {
1330                ExprKind::Var(var) => w!(cx, f, "{:?}", var),
1331                ExprKind::Local(local) => w!(cx, f, "{:?}", ^local),
1332                ExprKind::ConstDefId(did) => w!(cx, f, "{}", ^def_id_to_string(*did)),
1333                ExprKind::Constant(c) => w!(cx, f, "{:?}", c),
1334
1335                ExprKind::BinaryOp(op, e1, e2) => {
1336                    if should_parenthesize(op, e1) {
1337                        w!(cx, f, "({:?})", e1)?;
1338                    } else {
1339                        w!(cx, f, "{:?}", e1)?;
1340                    }
1341                    if matches!(op, BinOp::Div(_)) {
1342                        w!(cx, f, "{:?}", op)?;
1343                    } else {
1344                        w!(cx, f, " {:?} ", op)?;
1345                    }
1346                    if should_parenthesize(op, e2) {
1347                        w!(cx, f, "({:?})", e2)?;
1348                    } else {
1349                        w!(cx, f, "{:?}", e2)?;
1350                    }
1351                    Ok(())
1352                }
1353                ExprKind::UnaryOp(op, e) => {
1354                    if e.is_atom() {
1355                        w!(cx, f, "{:?}{:?}", op, e)
1356                    } else {
1357                        w!(cx, f, "{:?}({:?})", op, e)
1358                    }
1359                }
1360                ExprKind::FieldProj(e, proj) if let ExprKind::Ctor(_, _) = e.kind() => {
1361                    // special case to avoid printing `{n:12}.n` as `12.n` but instead, just print `12`
1362                    // TODO: maintain an invariant that `FieldProj` never has a Ctor as first argument (as always reduced)
1363                    w!(cx, f, "{:?}", e.proj_and_reduce(*proj))
1364                }
1365                ExprKind::FieldProj(e, proj) => {
1366                    if e.is_atom() {
1367                        w!(cx, f, "{:?}.{}", e, ^fmt_field_proj(cx, *proj))
1368                    } else {
1369                        w!(cx, f, "({:?}).{}", e, ^fmt_field_proj(cx, *proj))
1370                    }
1371                }
1372                ExprKind::Tuple(flds) => {
1373                    if let [e] = &flds[..] {
1374                        w!(cx, f, "({:?},)", e)
1375                    } else {
1376                        w!(cx, f, "({:?})", join!(", ", flds))
1377                    }
1378                }
1379                ExprKind::IsCtor(def_id, variant_idx, idx) => {
1380                    w!(cx, f, "({:?} is {:?}::{:?})", idx, def_id, ^variant_idx)
1381                }
1382                ExprKind::Ctor(ctor, flds) => {
1383                    let def_id = ctor.def_id();
1384                    if let Some(adt_sort_def) = cx.adt_sort_def_of(def_id) {
1385                        let variant = adt_sort_def.variant(ctor.variant_idx()).field_names();
1386                        let fields = iter::zip(variant, flds)
1387                            .map(|(name, value)| FieldBind { name: *name, value: value.clone() })
1388                            .collect_vec();
1389                        match ctor {
1390                            Ctor::Struct(_) => {
1391                                w!(cx, f, "{:?} {{ {:?} }}", def_id, join!(", ", fields))
1392                            }
1393                            Ctor::Enum(_, idx) => {
1394                                if fields.is_empty() {
1395                                    w!(cx, f, "{:?}::{:?}", def_id, ^idx.index())
1396                                } else {
1397                                    w!(cx, f, "{:?}::{:?}({:?})", def_id, ^idx.index(), join!(", ", fields))
1398                                }
1399                            }
1400                        }
1401                    } else {
1402                        match ctor {
1403                            Ctor::Struct(_) => {
1404                                w!(cx, f, "{:?} {{ {:?} }}", def_id, join!(", ", flds))
1405                            }
1406                            Ctor::Enum(_, idx) => {
1407                                w!(cx, f, "{:?}::{:?} {{ {:?} }}", def_id, ^idx, join!(", ", flds))
1408                            }
1409                        }
1410                    }
1411                }
1412                ExprKind::PathProj(e, field) => {
1413                    if e.is_atom() {
1414                        w!(cx, f, "{:?}.{:?}", e, field)
1415                    } else {
1416                        w!(cx, f, "({:?}).{:?}", e, field)
1417                    }
1418                }
1419                ExprKind::App(func, _, args) => {
1420                    w!(cx, f, "{:?}({})",
1421                        parens!(func, !func.is_atom()),
1422                        ^args
1423                            .iter()
1424                            .format_with(", ", |arg, f| f(&format_args_cx!(cx, "{:?}", arg)))
1425                    )
1426                }
1427                ExprKind::IfThenElse(p, e1, e2) => {
1428                    w!(cx, f, "if {:?} {{ {:?} }} else {{ {:?} }}", p, e1, e2)
1429                }
1430                ExprKind::Hole(_) => {
1431                    w!(cx, f, "*")
1432                }
1433                ExprKind::KVar(kvar) => {
1434                    w!(cx, f, "{:?}", kvar)
1435                }
1436                ExprKind::Alias(alias, args) => {
1437                    w!(cx, f, "{:?}({:?})", alias, join!(", ", args))
1438                }
1439                ExprKind::Abs(lam) => {
1440                    w!(cx, f, "{:?}", lam)
1441                }
1442                ExprKind::GlobalFunc(SpecFuncKind::Def(did) | SpecFuncKind::Uif(did)) => {
1443                    w!(cx, f, "{}", ^did.name())
1444                }
1445                ExprKind::GlobalFunc(SpecFuncKind::Thy(itf)) => {
1446                    if let Some(name) = name_of_thy_func(*itf) {
1447                        w!(cx, f, "{}", ^name)
1448                    } else {
1449                        w!(cx, f, "<error>")
1450                    }
1451                }
1452                ExprKind::InternalFunc(func) => {
1453                    w!(cx, f, "{:?}", func)
1454                }
1455                ExprKind::ForAll(expr) => {
1456                    let vars = expr.vars();
1457                    cx.with_bound_vars(vars, || {
1458                        if !vars.is_empty() {
1459                            cx.fmt_bound_vars(false, "∀", vars, ". ", f)?;
1460                        }
1461                        w!(cx, f, "{:?}", expr.skip_binder_ref())
1462                    })
1463                }
1464                ExprKind::Exists(expr) => {
1465                    let vars = expr.vars();
1466                    cx.with_bound_vars(vars, || {
1467                        if !vars.is_empty() {
1468                            cx.fmt_bound_vars(false, "∃", vars, ". ", f)?;
1469                        }
1470                        w!(cx, f, "{:?}", expr.skip_binder_ref())
1471                    })
1472                }
1473                ExprKind::BoundedQuant(kind, rng, body) => {
1474                    let vars = body.vars();
1475                    cx.with_bound_vars(vars, || {
1476                        w!(
1477                            cx,
1478                            f,
1479                            "{:?} {}..{} {{ {:?} }}",
1480                            kind,
1481                            ^rng.start,
1482                            ^rng.end,
1483                            body.skip_binder_ref()
1484                        )
1485                    })
1486                }
1487                ExprKind::Let(init, body) => {
1488                    let vars = body.vars();
1489                    cx.with_bound_vars(vars, || {
1490                        cx.fmt_bound_vars(false, "(let ", vars, " = ", f)?;
1491                        w!(cx, f, "{:?} in {:?})", init, body.skip_binder_ref())
1492                    })
1493                }
1494            }
1495        }
1496    }
1497
1498    fn fmt_field_proj(cx: &PrettyCx, proj: FieldProj) -> String {
1499        if let FieldProj::Adt { def_id, field } = proj
1500            && let Some(adt_sort_def) = cx.adt_sort_def_of(def_id)
1501        {
1502            format!("{}", adt_sort_def.struct_variant().field_names()[field as usize])
1503        } else {
1504            format!("{}", proj.field_idx())
1505        }
1506    }
1507
1508    impl Pretty for Constant {
1509        fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1510            match self {
1511                Constant::Int(i) => w!(cx, f, "{i}"),
1512                Constant::BitVec(i, sz) => w!(cx, f, "bv({i}, {sz})"),
1513                Constant::Real(r) => w!(cx, f, "{}.0", ^r.0),
1514                Constant::Bool(b) => w!(cx, f, "{b}"),
1515                Constant::Str(sym) => w!(cx, f, "\"{sym}\""),
1516                Constant::Char(c) => w!(cx, f, "\'{c}\'"),
1517            }
1518        }
1519    }
1520
1521    impl Pretty for AliasReft {
1522        fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1523            w!(cx, f, "<({:?}) as {:?}", &self.args[0], self.assoc_id.parent())?;
1524            let args = &self.args[1..];
1525            if !args.is_empty() {
1526                w!(cx, f, "<{:?}>", join!(", ", args))?;
1527            }
1528            w!(cx, f, ">::{}", ^self.assoc_id.name())
1529        }
1530    }
1531
1532    impl Pretty for Lambda {
1533        fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1534            let vars = self.body.vars();
1535            // TODO: remove redundant vars; see Ty
1536            // let redundant_bvars = self.body.redundant_bvars().into_iter().collect();
1537            cx.with_bound_vars(vars, || {
1538                cx.fmt_bound_vars(false, "λ", vars, ". ", f)?;
1539                w!(cx, f, "{:?}", self.body.as_ref().skip_binder())
1540            })
1541        }
1542    }
1543
1544    impl Pretty for Var {
1545        fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1546            match self {
1547                Var::Bound(debruijn, var) => cx.fmt_bound_reft(*debruijn, *var, f),
1548                Var::EarlyParam(var) => w!(cx, f, "{}", ^var.name),
1549                Var::Free(name) => w!(cx, f, "{:?}", ^name),
1550                Var::EVar(evar) => w!(cx, f, "{:?}", ^evar),
1551                Var::ConstGeneric(param) => w!(cx, f, "{}", ^param.name),
1552            }
1553        }
1554    }
1555
1556    impl Pretty for KVar {
1557        fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1558            w!(cx, f, "{:?}", ^self.kvid)?;
1559            match cx.kvar_args {
1560                KVarArgs::All => {
1561                    w!(
1562                        cx,
1563                        f,
1564                        "({:?})[{:?}]",
1565                        join!(", ", self.self_args()),
1566                        join!(", ", self.scope())
1567                    )?;
1568                }
1569                KVarArgs::SelfOnly => w!(cx, f, "({:?})", join!(", ", self.self_args()))?,
1570                KVarArgs::Hide => {}
1571            }
1572            Ok(())
1573        }
1574    }
1575
1576    impl Pretty for Path {
1577        fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1578            w!(cx, f, "{:?}", &self.loc)?;
1579            for field in &self.projection {
1580                w!(cx, f, ".{}", ^u32::from(*field))?;
1581            }
1582            Ok(())
1583        }
1584    }
1585
1586    impl Pretty for Loc {
1587        fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1588            match self {
1589                Loc::Local(local) => w!(cx, f, "{:?}", ^local),
1590                Loc::Var(var) => w!(cx, f, "{:?}", var),
1591            }
1592        }
1593    }
1594
1595    impl Pretty for BinOp {
1596        fn fmt(&self, _cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1597            match self {
1598                BinOp::Iff => w!(cx, f, "⇔"),
1599                BinOp::Imp => w!(cx, f, "⇒"),
1600                BinOp::Or => w!(cx, f, "∨"),
1601                BinOp::And => w!(cx, f, "∧"),
1602                BinOp::Eq => w!(cx, f, "="),
1603                BinOp::Ne => w!(cx, f, "≠"),
1604                BinOp::Gt(_) => w!(cx, f, ">"),
1605                BinOp::Ge(_) => w!(cx, f, "≥"),
1606                BinOp::Lt(_) => w!(cx, f, "<"),
1607                BinOp::Le(_) => w!(cx, f, "≤"),
1608                BinOp::Add(_) => w!(cx, f, "+"),
1609                BinOp::Sub(_) => w!(cx, f, "-"),
1610                BinOp::Mul(_) => w!(cx, f, "*"),
1611                BinOp::Div(_) => w!(cx, f, "/"),
1612                BinOp::Mod(_) => w!(cx, f, "mod"),
1613                BinOp::BitAnd => w!(cx, f, "&"),
1614                BinOp::BitOr => w!(cx, f, "|"),
1615                BinOp::BitXor => w!(cx, f, "^"),
1616                BinOp::BitShl => w!(cx, f, "<<"),
1617                BinOp::BitShr => w!(cx, f, ">>"),
1618            }
1619        }
1620    }
1621
1622    impl Pretty for UnOp {
1623        fn fmt(&self, _cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1624            match self {
1625                UnOp::Not => w!(cx, f, "¬"),
1626                UnOp::Neg => w!(cx, f, "-"),
1627            }
1628        }
1629    }
1630
1631    impl_debug_with_default_cx!(Expr, Loc, Path, Var, KVar, Lambda, AliasReft);
1632
1633    impl PrettyNested for Lambda {
1634        fn fmt_nested(&self, cx: &PrettyCx) -> Result<NestedString, fmt::Error> {
1635            // TODO: remove redundant vars; see Ty
1636            nested_with_bound_vars(cx, "λ", self.body.vars(), None, |prefix| {
1637                let expr_d = self.body.skip_binder_ref().fmt_nested(cx)?;
1638                let text = format!("{}{}", prefix, expr_d.text);
1639                Ok(NestedString { text, children: expr_d.children, key: None })
1640            })
1641        }
1642    }
1643
1644    pub fn aggregate_nested(
1645        cx: &PrettyCx,
1646        ctor: &Ctor,
1647        flds: &[Expr],
1648        is_named: bool,
1649    ) -> Result<NestedString, fmt::Error> {
1650        let def_id = ctor.def_id();
1651        let mut text =
1652            if is_named && ctor.is_enum() { format_cx!(cx, "{:?}", ctor) } else { "".to_string() };
1653        if flds.is_empty() {
1654            // No fields, no index
1655            Ok(NestedString { text, children: None, key: None })
1656        } else if flds.len() == 1 {
1657            // Single field, inline index
1658            text += &format_cx!(cx, "{:?}", flds[0].clone());
1659            Ok(NestedString { text, children: None, key: None })
1660        } else {
1661            let keys = if let Some(adt_sort_def) = cx.adt_sort_def_of(def_id) {
1662                adt_sort_def
1663                    .variant(ctor.variant_idx())
1664                    .field_names()
1665                    .iter()
1666                    .map(|name| format!("{name}"))
1667                    .collect_vec()
1668            } else {
1669                (0..flds.len()).map(|i| format!("arg{i}")).collect_vec()
1670            };
1671            // Multiple fields, nested index
1672            text += "{..}";
1673            let mut children = vec![];
1674            for (key, fld) in iter::zip(keys, flds) {
1675                let fld_d = fld.fmt_nested(cx)?;
1676                children.push(NestedString { key: Some(key), ..fld_d });
1677            }
1678            Ok(NestedString { text, children: Some(children), key: None })
1679        }
1680    }
1681
1682    impl PrettyNested for Expr {
1683        fn fmt_nested(&self, cx: &PrettyCx) -> Result<NestedString, fmt::Error> {
1684            let e = if cx.simplify_exprs {
1685                self.simplify(&SnapshotMap::default())
1686            } else {
1687                self.clone()
1688            };
1689            match e.kind() {
1690                ExprKind::Var(..)
1691                | ExprKind::Local(..)
1692                | ExprKind::Constant(..)
1693                | ExprKind::ConstDefId(..)
1694                | ExprKind::Hole(..)
1695                | ExprKind::GlobalFunc(..)
1696                | ExprKind::InternalFunc(..)
1697                | ExprKind::KVar(..) => debug_nested(cx, &e),
1698
1699                ExprKind::IfThenElse(p, e1, e2) => {
1700                    let p_d = p.fmt_nested(cx)?;
1701                    let e1_d = e1.fmt_nested(cx)?;
1702                    let e2_d = e2.fmt_nested(cx)?;
1703                    let text = format!("(if {} then {} else {})", p_d.text, e1_d.text, e2_d.text);
1704                    let children = float_children(vec![p_d.children, e1_d.children, e2_d.children]);
1705                    Ok(NestedString { text, children, key: None })
1706                }
1707                ExprKind::BinaryOp(op, e1, e2) => {
1708                    let e1_d = e1.fmt_nested(cx)?;
1709                    let e2_d = e2.fmt_nested(cx)?;
1710                    let e1_text = if should_parenthesize(op, e1) {
1711                        format!("({})", e1_d.text)
1712                    } else {
1713                        e1_d.text
1714                    };
1715                    let e2_text = if should_parenthesize(op, e2) {
1716                        format!("({})", e2_d.text)
1717                    } else {
1718                        e2_d.text
1719                    };
1720                    let op_d = debug_nested(cx, op)?;
1721                    let op_text = if matches!(op, BinOp::Div(_)) {
1722                        op_d.text
1723                    } else {
1724                        format!(" {} ", op_d.text)
1725                    };
1726                    let text = format!("{e1_text}{op_text}{e2_text}");
1727                    let children = float_children(vec![e1_d.children, e2_d.children]);
1728                    Ok(NestedString { text, children, key: None })
1729                }
1730                ExprKind::UnaryOp(op, e) => {
1731                    let e_d = e.fmt_nested(cx)?;
1732                    let op_d = debug_nested(cx, op)?;
1733                    let text = if e.is_atom() {
1734                        format!("{}{}", op_d.text, e_d.text)
1735                    } else {
1736                        format!("{}({})", op_d.text, e_d.text)
1737                    };
1738                    Ok(NestedString { text, children: e_d.children, key: None })
1739                }
1740                ExprKind::FieldProj(e, proj) if let ExprKind::Ctor(_, _) = e.kind() => {
1741                    // special case to avoid printing `{n:12}.n` as `12.n` but instead, just print `12`
1742                    // TODO: maintain an invariant that `FieldProj` never has a Ctor as first argument (as always reduced)
1743                    e.proj_and_reduce(*proj).fmt_nested(cx)
1744                }
1745                ExprKind::FieldProj(e, proj) => {
1746                    let e_d = e.fmt_nested(cx)?;
1747                    let text = if e.is_atom() {
1748                        format!("{}.{}", e_d.text, fmt_field_proj(cx, *proj))
1749                    } else {
1750                        format!("({}).{}", e_d.text, fmt_field_proj(cx, *proj))
1751                    };
1752                    Ok(NestedString { text, children: e_d.children, key: None })
1753                }
1754                ExprKind::Tuple(flds) => {
1755                    let mut texts = vec![];
1756                    let mut kidss = vec![];
1757                    for e in flds {
1758                        let e_d = e.fmt_nested(cx)?;
1759                        texts.push(e_d.text);
1760                        kidss.push(e_d.children);
1761                    }
1762                    let text = if let [e] = &texts[..] {
1763                        format!("({e},)")
1764                    } else {
1765                        format!("({})", texts.join(", "))
1766                    };
1767                    let children = float_children(kidss);
1768                    Ok(NestedString { text, children, key: None })
1769                }
1770                ExprKind::Ctor(ctor, flds) => aggregate_nested(cx, ctor, flds, true),
1771                ExprKind::IsCtor(def_id, variant_idx, idx) => {
1772                    let text = format!("is::{:?}::{:?}( {:?} )", def_id, variant_idx, idx);
1773                    Ok(NestedString { text, children: None, key: None })
1774                }
1775                ExprKind::PathProj(e, field) => {
1776                    let e_d = e.fmt_nested(cx)?;
1777                    let text = if e.is_atom() {
1778                        format!("{}.{:?}", e_d.text, field)
1779                    } else {
1780                        format!("({}).{:?}", e_d.text, field)
1781                    };
1782                    Ok(NestedString { text, children: e_d.children, key: None })
1783                }
1784                ExprKind::Alias(alias, args) => {
1785                    let mut texts = vec![];
1786                    let mut kidss = vec![];
1787                    for arg in args {
1788                        let arg_d = arg.fmt_nested(cx)?;
1789                        texts.push(arg_d.text);
1790                        kidss.push(arg_d.children);
1791                    }
1792                    let text = format_cx!(cx, "{:?}({:?})", alias, texts.join(", "));
1793                    let children = float_children(kidss);
1794                    Ok(NestedString { text, children, key: None })
1795                }
1796                ExprKind::App(func, _, args) => {
1797                    let func_d = func.fmt_nested(cx)?;
1798                    let mut texts = vec![];
1799                    let mut kidss = vec![func_d.children];
1800                    for arg in args {
1801                        let arg_d = arg.fmt_nested(cx)?;
1802                        texts.push(arg_d.text);
1803                        kidss.push(arg_d.children);
1804                    }
1805                    let text = if func.is_atom() {
1806                        format!("{}({})", func_d.text, texts.join(", "))
1807                    } else {
1808                        format!("({})({})", func_d.text, texts.join(", "))
1809                    };
1810                    let children = float_children(kidss);
1811                    Ok(NestedString { text, children, key: None })
1812                }
1813                ExprKind::Abs(lambda) => lambda.fmt_nested(cx),
1814                ExprKind::Let(init, body) => {
1815                    // FIXME this is very wrong!
1816                    nested_with_bound_vars(cx, "let", body.vars(), None, |prefix| {
1817                        let body = body.skip_binder_ref().fmt_nested(cx)?;
1818                        let text = format!("{:?} {}{}", init, prefix, body.text);
1819                        Ok(NestedString { text, children: body.children, key: None })
1820                    })
1821                }
1822                ExprKind::BoundedQuant(kind, rng, body) => {
1823                    let left = match kind {
1824                        fhir::QuantKind::Forall => "∀",
1825                        fhir::QuantKind::Exists => "∃",
1826                    };
1827                    let right = Some(format!(" in {}..{}", rng.start, rng.end));
1828
1829                    nested_with_bound_vars(cx, left, body.vars(), right, |all_str| {
1830                        let expr_d = body.as_ref().skip_binder().fmt_nested(cx)?;
1831                        let text = format!("{}{}", all_str, expr_d.text);
1832                        Ok(NestedString { text, children: expr_d.children, key: None })
1833                    })
1834                }
1835                ExprKind::ForAll(expr) => {
1836                    nested_with_bound_vars(cx, "∀", expr.vars(), None, |all_str| {
1837                        let expr_d = expr.as_ref().skip_binder().fmt_nested(cx)?;
1838                        let text = format!("{}{}", all_str, expr_d.text);
1839                        Ok(NestedString { text, children: expr_d.children, key: None })
1840                    })
1841                }
1842                ExprKind::Exists(expr) => {
1843                    nested_with_bound_vars(cx, "∀", expr.vars(), None, |all_str| {
1844                        let expr_d = expr.as_ref().skip_binder().fmt_nested(cx)?;
1845                        let text = format!("{}{}", all_str, expr_d.text);
1846                        Ok(NestedString { text, children: expr_d.children, key: None })
1847                    })
1848                }
1849            }
1850        }
1851    }
1852}