Skip to main content

pearlite_syn/
term.rs

1use proc_macro2::{Delimiter, Span};
2use syn::{Pat, parse::discouraged::AnyDelimiter, punctuated::Punctuated, *};
3
4#[cfg(feature = "printing")]
5use quote::IdentFragment;
6#[cfg(feature = "printing")]
7use std::fmt::{self, Display};
8use std::hash::{Hash, Hasher};
9#[cfg(feature = "parsing")]
10use std::mem;
11
12mod kw {
13    syn::custom_keyword!(forall);
14    syn::custom_keyword!(exists);
15    syn::custom_keyword!(dead);
16    syn::custom_keyword!(trigger);
17    syn::custom_keyword!(pearlite);
18    syn::custom_keyword!(seq);
19    syn::custom_keyword!(proof_assert);
20}
21
22ast_enum_of_structs! {
23    /// A Pearlite term.
24    ///
25    /// For information about Syn enums, consult [syn::Expr]
26    pub enum Term {
27        /// A slice literal term: `[a, b, c, d]`.
28        Array(TermArray),
29
30        /// A binary operation: `a + b`, `a * b`.
31        Binary(TermBinary),
32
33        /// A blocked scope: `{ ... }`.
34        Block(TermBlock),
35
36        /// A function call term: `invoke(a, b)`.
37        Call(TermCall),
38
39        /// A cast term: `foo as f64`.
40        Cast(TermCast),
41
42        /// Access of a named struct field (`obj.k`) or unnamed tuple struct
43        /// field (`obj.0`).
44        Field(TermField),
45
46        /// An term contained within invisible delimiters.
47        ///
48        /// This variant is important for faithfully representing the precedence
49        /// of expressions and is related to `None`-delimited spans in a
50        /// `TokenStream`.
51        Group(TermGroup),
52
53        /// An `if` term with an optional `else` block: `if expr { ... }
54        /// else { ... }`.
55        ///
56        /// The `else` branch term may only be an `If` or `Block`
57        /// term, not any of the other types of term.
58        If(TermIf),
59
60        /// A square bracketed indexing term: `vector[2]`.
61        Index(TermIndex),
62
63        /// A `let` guard: `let Some(x) = opt`.
64        Let(TermLet),
65
66        /// A literal in place of an term: `1`, `"foo"`.
67        Lit(TermLit),
68
69        /// A `match` term: `match n { Some(n) => {}, None => {} }`.
70        Match(TermMatch),
71
72        /// A method call term: `x.foo::<T>(a, b)`.
73        MethodCall(TermMethodCall),
74
75        /// A parenthesized term: `(a + b)`.
76        Paren(TermParen),
77
78        /// A path like `std::mem::replace` possibly containing generic
79        /// parameters and a qualified self-type.
80        ///
81        /// A plain identifier like `x` is a path of length 1.
82        Path(TermPath),
83
84        /// A range term: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
85        Range(TermRange),
86
87        /// A referencing operation: `&a` or `&mut a`.
88        Reference(TermReference),
89
90        /// An array literal constructed from one repeated element: `[0u8; N]`.
91        Repeat(TermRepeat),
92
93        /// A struct literal term: `Point { x: 1, y: 1 }`.
94        ///
95        /// The `rest` provides the value of the remaining fields as in `S { a:
96        /// 1, b: 1, ..rest }`.
97        Struct(TermStruct),
98
99        /// A tuple term: `(a, b, c, d)`.
100        Tuple(TermTuple),
101
102        /// A type ascription term: `foo: f64`.
103        Type(TermType),
104
105        /// A unary operation: `!x`, `*x`.
106        Unary(TermUnary),
107
108        /// The final value of a borrow: `^x`
109        Final(TermFinal),
110
111        /// The view of a term: `x@`
112        View(TermView),
113
114        /// Logical implication
115        Impl(TermImpl),
116
117        /// Logical quantification
118        Quant(TermQuant),
119
120        /// POlymorphic placeholder for pealite code that won't be translated
121        Dead(TermDead),
122
123        /// Pearlite macro `pearlite!{ ... }`.
124        Pearlite(TermPearlite),
125
126        /// Macro `proof_assert!{ ... }`.
127        ProofAssert(TermProofAssert),
128
129        /// Macro `seq!{ ... }`.
130        Seq(TermSeq),
131
132        /// A closure expresion: |a, b| a + b.
133        Closure(TermClosure),
134
135        #[doc(hidden)]
136        __Nonexhaustive,
137    }
138}
139
140ast_enum_of_structs! {
141    pub enum EnsuresTerm {
142        TermWithTriggers(TermWithTriggers),
143        EnsuresClosure(EnsuresClosure),
144    }
145}
146
147ast_struct! {
148    pub struct EnsuresClosure {
149        pub or1_token: Token![|],
150        pub result: Pat,
151        pub or2_token: Token![|],
152        pub body: Box<TermWithTriggers>,
153    }
154}
155
156ast_struct! {
157    // A blocked scope: `{ ... }`.
158    pub struct TermBlock {
159        pub brace_token: token::Brace,
160        /// Statements in a block
161        pub stmts: Vec<TermStmt>,
162    }
163}
164
165ast_enum! {
166    /// A statement, usually ending in a semicolon.
167    #[derive(Debug)]
168    pub enum TermStmt {
169        /// A local (let) binding.
170        Local(TLocal),
171
172        /// An item definition.
173        Item(Item),
174
175        /// Expr without trailing semicolon.
176        Expr(Term),
177
178        /// Expression with trailing semicolon.
179        Semi(Term, Token![;]),
180
181        /// Empty statement
182        Empty(Token![;]),
183    }
184}
185
186ast_struct! {
187    /// A local `let` binding: `let x: u64 = s.parse()?`.
188    pub struct TLocal {
189        pub let_token: Token![let],
190        pub pat: Pat,
191        pub init: Option<(Token![=], Box<Term>)>,
192        pub semi_token: Token![;],
193    }
194}
195
196ast_struct! {
197    /// A slice literal term: `[a, b, c, d]`.
198    pub struct TermArray #full {
199        pub bracket_token: token::Bracket,
200        pub elems: Punctuated<Term, Token![,]>,
201    }
202}
203
204ast_struct! {
205    /// A binary operation: `a + b`, `a * b`.
206    pub struct TermBinary {
207        pub left: Box<Term>,
208        pub op: BinOp,
209        pub right: Box<Term>,
210    }
211}
212
213ast_struct! {
214    /// A function call term: `invoke(a, b)`.
215    pub struct TermCall {
216        pub func: Box<Term>,
217        pub paren_token: token::Paren,
218        pub args: Punctuated<Term, Token![,]>,
219    }
220}
221
222ast_struct! {
223    /// A cast term: `foo as f64`.
224    pub struct TermCast {
225        pub expr: Box<Term>,
226        pub as_token: Token![as],
227        pub ty: Box<Type>,
228    }
229}
230
231ast_struct! {
232    /// A closure expression: `|a, b| a + b`.
233    pub struct TermClosure #full {
234        pub attrs: Vec<Attribute>,
235        pub or1_token: Token![|],
236        pub inputs: Punctuated<Pat, Token![,]>,
237        pub or2_token: Token![|],
238        pub output: ReturnType,
239        pub body: Box<Term>,
240    }
241}
242
243ast_struct! {
244    /// Access of a named struct field (`obj.k`) or unnamed tuple struct
245    /// field (`obj.0`).
246    pub struct TermField {
247        pub base: Box<Term>,
248        pub dot_token: Token![.],
249        pub member: Member,
250    }
251}
252
253ast_struct! {
254    /// An term contained within invisible delimiters.
255    ///
256    /// This variant is important for faithfully representing the precedence
257    /// of expressions and is related to `None`-delimited spans in a
258    /// `TokenStream`.
259    pub struct TermGroup #full {
260        pub group_token: token::Group,
261        pub expr: Box<Term>,
262    }
263}
264
265ast_struct! {
266    /// An `if` term with an optional `else` block: `if expr { ... }
267    /// else { ... }`.
268    ///
269    /// The `else` branch term may only be an `If` or `Block`
270    /// term, not any of the other types of term.
271    pub struct TermIf #full {
272        pub if_token: Token![if],
273        pub cond: Box<Term>,
274        pub then_branch: TermBlock,
275        pub else_branch: Option<(Token![else], Box<Term>)>,
276    }
277}
278
279ast_struct! {
280    /// A square bracketed indexing term: `vector[2]`.
281    pub struct TermIndex {
282        pub expr: Box<Term>,
283        pub bracket_token: token::Bracket,
284        pub index: Box<Term>,
285    }
286}
287
288ast_struct! {
289    /// A `let` guard: `let Some(x) = opt`.
290    pub struct TermLet #full {
291        pub let_token: Token![let],
292        pub pat: Pat,
293        pub eq_token: Token![=],
294        pub expr: Box<Term>,
295    }
296}
297
298ast_struct! {
299    /// A literal in place of an term: `1`, `"foo"`.
300    pub struct TermLit {
301        pub lit: Lit,
302    }
303}
304
305ast_struct! {
306    /// A `match` term: `match n { Some(n) => {}, None => {} }`.
307    pub struct TermMatch #full {
308        pub match_token: Token![match],
309        pub expr: Box<Term>,
310        pub brace_token: token::Brace,
311        pub arms: Vec<TermArm>,
312    }
313}
314
315ast_struct! {
316    /// A method call term: `x.foo::<T>(a, b)`.
317    pub struct TermMethodCall #full {
318        pub receiver: Box<Term>,
319        pub dot_token: Token![.],
320        pub method: Ident,
321        pub turbofish: Option<TermMethodTurbofish>,
322        pub paren_token: token::Paren,
323        pub args: Punctuated<Term, Token![,]>,
324    }
325}
326
327ast_struct! {
328    /// A parenthesized term: `(a + b)`.
329    pub struct TermParen {
330        pub paren_token: token::Paren,
331        pub expr: Box<Term>,
332    }
333}
334
335ast_struct! {
336    /// A path like `std::mem::replace` possibly containing generic
337    /// parameters and a qualified self-type.
338    ///
339    /// A plain identifier like `x` is a path of length 1.
340    pub struct TermPath {
341        pub inner: ExprPath,
342        // pub qself: Option<QSelf>,
343        // pub path: Path,
344    }
345}
346
347ast_struct! {
348    /// A range term: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
349    pub struct TermRange #full {
350        pub from: Option<Box<Term>>,
351        pub limits: RangeLimits,
352        pub to: Option<Box<Term>>,
353    }
354}
355
356ast_struct! {
357    /// A referencing operation: `&a` or `&mut a`.
358    pub struct TermReference #full {
359        pub and_token: Token![&],
360        pub mutability: Option<Token![mut]>,
361        pub expr: Box<Term>,
362    }
363}
364
365ast_struct! {
366    /// An array literal constructed from one repeated element: `[0u8; N]`.
367    pub struct TermRepeat #full {
368        pub bracket_token: token::Bracket,
369        pub expr: Box<Term>,
370        pub semi_token: Token![;],
371        pub len: Box<Term>,
372    }
373}
374
375ast_struct! {
376    /// A struct literal term: `Point { x: 1, y: 1 }`.
377    ///
378    /// The `rest` provides the value of the remaining fields as in `S { a:
379    /// 1, b: 1, ..rest }`.
380    pub struct TermStruct #full {
381        pub path: Path,
382        pub brace_token: token::Brace,
383        pub fields: Punctuated<TermFieldValue, Token![,]>,
384        pub dot2_token: Option<Token![..]>,
385        pub rest: Option<Box<Term>>,
386    }
387}
388
389ast_struct! {
390    /// A tuple term: `(a, b, c, d)`.
391    pub struct TermTuple #full {
392        pub paren_token: token::Paren,
393        pub elems: Punctuated<Term, Token![,]>,
394    }
395}
396
397ast_struct! {
398    /// A type ascription term: `foo: f64`.
399    pub struct TermType #full {
400        pub expr: Box<Term>,
401        pub colon_token: Token![:],
402        pub ty: Box<Type>,
403    }
404}
405
406ast_struct! {
407    /// A unary operation: `!x`, `*x`.
408    pub struct TermUnary {
409        pub op: UnOp,
410        pub expr: Box<Term>,
411    }
412}
413
414ast_struct! {
415    pub struct TermImpl {
416        pub hyp: Box<Term>,
417        pub eqeq_token: Token![==],
418        pub gt_token: Token![>],
419        pub cons: Box<Term>,
420    }
421}
422
423ast_struct! {
424    pub struct TermFinal {
425        pub final_token: Token![^],
426        pub term: Box<Term>
427    }
428}
429
430ast_struct! {
431    pub struct TermView {
432        pub term: Box<Term>,
433        pub at_token: Token![@],
434    }
435}
436
437ast_struct! {
438    pub struct TermQuant {
439        pub quant_token: QuantToken,
440        pub lt_token: Token![<],
441        pub args: Punctuated<QuantArg, Token![,]>,
442        pub gt_token: Token![>],
443        pub term: TermWithTriggers
444    }
445}
446
447ast_struct! {
448    pub struct TermWithTriggers {
449        pub trigger: Vec<Trigger>,
450        pub term: Box<Term>
451    }
452}
453
454use kw::{exists, forall};
455ast_enum_of_structs! {
456    pub enum QuantToken {
457        Forall(forall),
458        Exists(exists),
459    }
460}
461
462ast_struct! {
463    pub struct QuantArg {
464        pub ident: Ident,
465        pub ty: Option<(Token![:], Box<Type>)>,
466    }
467}
468
469ast_struct! {
470    pub struct Trigger {
471        pub pound_token: Token![#],
472        pub bracket_token: token::Bracket,
473        pub trigger_token: kw::trigger,
474        pub paren_token: token::Paren,
475        pub terms: Punctuated<Term, Token![,]>,
476    }
477}
478
479ast_struct! {
480    pub struct TermDead {
481        pub dead_token: kw::dead
482    }
483}
484
485ast_struct! {
486    pub struct TermPearlite {
487        pub pearlite_token: kw::pearlite,
488        pub bang_token: Token![!],
489        pub block: TermBlock,
490    }
491}
492
493ast_struct! {
494    pub struct TermProofAssert {
495        pub proof_assert_token: kw::proof_assert,
496        pub bang_token: Token![!],
497        pub block: TermBlock,
498    }
499}
500
501ast_struct! {
502    pub struct TermSeq {
503        pub seq_token: kw::seq,
504        pub bang_token: Token![!],
505        pub bracket_token: token::Bracket,
506        pub terms: Punctuated<Term, Token![,]>,
507    }
508}
509
510ast_struct! {
511    /// The index of an unnamed tuple struct field.
512    pub struct Index {
513        pub index: u32,
514        pub span: Span,
515    }
516}
517
518impl From<usize> for Index {
519    fn from(index: usize) -> Index {
520        assert!(index < u32::MAX as usize);
521        Index { index: index as u32, span: Span::call_site() }
522    }
523}
524
525impl Eq for Index {}
526
527impl PartialEq for Index {
528    fn eq(&self, other: &Self) -> bool {
529        self.index == other.index
530    }
531}
532
533impl Hash for Index {
534    fn hash<H: Hasher>(&self, state: &mut H) {
535        self.index.hash(state);
536    }
537}
538
539#[cfg(feature = "printing")]
540impl IdentFragment for Index {
541    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
542        Display::fmt(&self.index, formatter)
543    }
544
545    fn span(&self) -> Option<Span> {
546        Some(self.span)
547    }
548}
549
550#[cfg(feature = "full")]
551ast_struct! {
552    /// The `::<>` explicit type parameters passed to a method call:
553    /// `parse::<u64>()`.
554    pub struct TermMethodTurbofish {
555        pub colon2_token: Token![::],
556        pub lt_token: Token![<],
557        pub args: Punctuated<TermGenericMethodArgument, Token![,]>,
558        pub gt_token: Token![>],
559    }
560}
561
562#[cfg(feature = "full")]
563ast_enum! {
564    /// An individual generic argument to a method, like `T`.
565    ///
566    #[derive(Debug)]
567    pub enum TermGenericMethodArgument {
568        /// A type argument.
569        Type(Type),
570        /// A const term. Must be inside of a block.
571        ///
572        /// NOTE: Identity expressions are represented as Type arguments, as
573        /// they are indistinguishable syntactically.
574        Const(Term),
575    }
576}
577
578#[cfg(feature = "full")]
579ast_struct! {
580    /// A field-value pair in a struct literal.
581    pub struct TermFieldValue {
582        /// Name or index of the field.
583        pub member: Member,
584
585        /// The colon in `Struct { x: x }`. If written in shorthand like
586        /// `Struct { x }`, there is no colon.
587        pub colon_token: Option<Token![:]>,
588
589        /// Value of the field.
590        pub expr: Term,
591    }
592}
593
594#[cfg(feature = "full")]
595ast_struct! {
596    /// One arm of a `match` term: `0...10 => { return true; }`.
597    ///
598    /// As in:
599    ///
600    /// ```
601    /// # fn f() -> bool {
602    /// #     let n = 0;
603    /// match n {
604    ///     0..=10 => {
605    ///         return true;
606    ///     }
607    ///     // ...
608    ///     # _ => {}
609    /// }
610    /// #   false
611    /// # }
612    /// ```
613    pub struct TermArm {
614        pub pat: Pat,
615        pub guard: Option<(Token![if], Box<Term>)>,
616        pub fat_arrow_token: Token![=>],
617        pub body: Box<Term>,
618        pub comma: Option<Token![,]>,
619    }
620}
621
622#[cfg(any(feature = "parsing", feature = "printing"))]
623#[cfg(feature = "full")]
624pub(crate) fn requires_terminator(expr: &Term) -> bool {
625    // see https://github.com/rust-lang/rust/blob/2679c38fc/src/librustc_ast/util/classify.rs#L7-L25
626    !matches!(*expr, Term::Block(..) | Term::If(..) | Term::Match(..))
627}
628
629#[cfg(feature = "parsing")]
630pub(crate) mod parsing {
631    use super::*;
632    use std::cmp::Ordering;
633    use syn::{
634        parse::{Parse, ParseStream, Result},
635        spanned::Spanned,
636    };
637
638    syn::custom_keyword!(raw);
639
640    // When we're parsing expressions which occur before blocks, like in an if
641    // statement's condition, we cannot parse a struct literal.
642    //
643    // Struct literals are ambiguous in certain positions
644    // https://github.com/rust-lang/rfcs/pull/92
645    pub struct AllowStruct(bool);
646
647    enum Precedence {
648        Any,
649        Assign,
650        Impl,
651        Range,
652        Or,
653        And,
654        Compare,
655        BitOr,
656        BitXor,
657        BitAnd,
658        Shift,
659        Arithmetic,
660        Term,
661        Cast,
662    }
663
664    impl Precedence {
665        fn of(op: &BinOp) -> Self {
666            match *op {
667                BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
668                BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
669                BinOp::And(_) => Precedence::And,
670                BinOp::Or(_) => Precedence::Or,
671                BinOp::BitXor(_) => Precedence::BitXor,
672                BinOp::BitAnd(_) => Precedence::BitAnd,
673                BinOp::BitOr(_) => Precedence::BitOr,
674                BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
675                BinOp::Eq(_)
676                | BinOp::Lt(_)
677                | BinOp::Le(_)
678                | BinOp::Ne(_)
679                | BinOp::Ge(_)
680                | BinOp::Gt(_) => Precedence::Compare,
681                BinOp::AddAssign(_)
682                | BinOp::SubAssign(_)
683                | BinOp::MulAssign(_)
684                | BinOp::DivAssign(_)
685                | BinOp::RemAssign(_)
686                | BinOp::BitXorAssign(_)
687                | BinOp::BitAndAssign(_)
688                | BinOp::BitOrAssign(_)
689                | BinOp::ShlAssign(_)
690                | BinOp::ShrAssign(_) => Precedence::Assign,
691                _ => unimplemented!(),
692            }
693        }
694    }
695
696    impl TermBlock {
697        pub fn parse_within(input: ParseStream) -> Result<Vec<TermStmt>> {
698            let mut stmts = Vec::new();
699            loop {
700                while let Some(semi) = input.parse::<Option<Token![;]>>()? {
701                    stmts.push(TermStmt::Empty(semi));
702                }
703                if input.is_empty() {
704                    break;
705                }
706                let s = parse_stmt(input, true)?;
707                let requires_semicolon =
708                    if let TermStmt::Expr(s) = &s { super::requires_terminator(s) } else { false };
709                stmts.push(s);
710                if input.is_empty() {
711                    break;
712                } else if requires_semicolon {
713                    return Err(input.error("unexpected token"));
714                }
715            }
716            Ok(stmts)
717        }
718    }
719
720    impl Parse for TermBlock {
721        fn parse(input: ParseStream) -> Result<Self> {
722            let content;
723            Ok(TermBlock {
724                brace_token: braced!(content in input),
725                stmts: content.call(TermBlock::parse_within)?,
726            })
727        }
728    }
729
730    impl Parse for TermStmt {
731        fn parse(input: ParseStream) -> Result<Self> {
732            parse_stmt(input, false)
733        }
734    }
735
736    pub(crate) fn replace_attrs(item: &mut Item, new: Vec<Attribute>) -> Vec<Attribute> {
737        match item {
738            Item::Const(ItemConst { attrs, .. })
739            | Item::Enum(ItemEnum { attrs, .. })
740            | Item::ExternCrate(ItemExternCrate { attrs, .. })
741            | Item::Fn(ItemFn { attrs, .. })
742            | Item::ForeignMod(ItemForeignMod { attrs, .. })
743            | Item::Impl(ItemImpl { attrs, .. })
744            | Item::Macro(ItemMacro { attrs, .. })
745            | Item::Mod(ItemMod { attrs, .. })
746            | Item::Static(ItemStatic { attrs, .. })
747            | Item::Struct(ItemStruct { attrs, .. })
748            | Item::Trait(ItemTrait { attrs, .. })
749            | Item::TraitAlias(ItemTraitAlias { attrs, .. })
750            | Item::Type(ItemType { attrs, .. })
751            | Item::Union(ItemUnion { attrs, .. })
752            | Item::Use(ItemUse { attrs, .. }) => mem::replace(attrs, new),
753            Item::Verbatim(_) | _ => Vec::new(),
754        }
755    }
756
757    fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<TermStmt> {
758        let mut attrs = input.call(Attribute::parse_outer)?;
759        if input.peek(Token![let]) {
760            stmt_local(input).map(TermStmt::Local)
761        } else if input.peek(Token![use]) {
762            let item: Item = input.parse()?;
763            Ok(TermStmt::Item(item))
764        } else if input.peek(Token![pub])
765            || input.peek(Token![crate]) && !input.peek2(Token![::])
766            || input.peek(Token![use])
767            || input.peek(Token![fn])
768            || input.peek(Token![mod])
769            || input.peek(Token![type])
770            || input.peek(Token![struct])
771            || input.peek(Token![enum])
772            || input.peek(Token![union]) && input.peek2(Ident)
773            || input.peek(Token![trait])
774            || input.peek(Token![impl])
775        {
776            let mut item: Item = input.parse()?;
777            attrs.extend(replace_attrs(&mut item, Vec::new()));
778            replace_attrs(&mut item, attrs);
779            Ok(TermStmt::Item(item))
780        } else {
781            stmt_expr(input, allow_nosemi)
782        }
783    }
784
785    fn stmt_local(input: ParseStream) -> Result<TLocal> {
786        Ok(TLocal {
787            let_token: input.parse()?,
788            pat: {
789                // let mut pat: Pat = pat::parsing::multi_pat_with_leading_vert(input)?;
790                let mut pat = Pat::parse_single(input)?;
791                if input.peek(Token![:]) {
792                    let colon_token: Token![:] = input.parse()?;
793                    let ty: Type = input.parse()?;
794                    pat = Pat::Type(PatType {
795                        attrs: Vec::new(),
796                        pat: Box::new(pat),
797                        colon_token,
798                        ty: Box::new(ty),
799                    });
800                }
801                pat
802            },
803            init: {
804                if input.peek(Token![=]) {
805                    let eq_token: Token![=] = input.parse()?;
806                    let init: Term = input.parse()?;
807                    Some((eq_token, Box::new(init)))
808                } else {
809                    None
810                }
811            },
812            semi_token: input.parse()?,
813        })
814    }
815
816    fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<TermStmt> {
817        let e = term_early(input)?;
818
819        if input.peek(Token![;]) {
820            return Ok(TermStmt::Semi(e, input.parse()?));
821        }
822
823        if allow_nosemi || !super::requires_terminator(&e) {
824            Ok(TermStmt::Expr(e))
825        } else {
826            Err(input.error("expected semicolon"))
827        }
828    }
829
830    impl Parse for Term {
831        fn parse(input: ParseStream) -> Result<Self> {
832            ambiguous_term(input, AllowStruct(true))
833        }
834    }
835
836    impl Term {
837        /// An alternative to the primary `Term::parse` parser (from the
838        /// [`Parse`] trait) for ambiguous syntactic positions in which a
839        /// trailing brace should not be taken as part of the term.
840        ///
841        /// Pearlite grammar has an ambiguity where braces sometimes turn a path
842        /// term into a struct initialization and sometimes do not. In the
843        /// following code, the term `S {}` is one term. Presumably
844        /// there is an empty struct `struct S {}` defined somewhere which it is
845        /// instantiating.
846        ///
847        /// ```
848        /// # struct S;
849        /// # impl std::ops::Deref for S {
850        /// #     type Target = bool;
851        /// #     fn deref(&self) -> &Self::Target {
852        /// #         &true
853        /// #     }
854        /// # }
855        /// let _ = *S {};
856        ///
857        /// // parsed by rustc as: `*(S {})`
858        /// ```
859        ///
860        /// We would want to parse the above using `Term::parse` after the `=`
861        /// token.
862        ///
863        /// But in the following, `S {}` is *not* a struct init term.
864        ///
865        /// ```
866        /// # const S: &bool = &true;
867        /// if *S {} {}
868        ///
869        /// // parsed by rustc as:
870        /// //
871        /// //    if (*S) {
872        /// //        /* empty block */
873        /// //    }
874        /// //    {
875        /// //        /* another empty block */
876        /// //    }
877        /// ```
878        ///
879        /// For that reason we would want to parse if-conditions using
880        /// `Term::parse_without_eager_brace` after the `if` token. Same for
881        /// similar syntactic positions such as the condition expr after a
882        /// `while` token or the expr at the top of a `match`.
883        ///
884        /// The Pearlite grammar's choices around which way this ambiguity is
885        /// resolved at various syntactic positions is fairly arbitrary. Really
886        /// either parse behavior could work in most positions, and language
887        /// designers just decide each case based on which is more likely to be
888        /// what the programmer had in mind most of the time.
889        ///
890        /// ```
891        /// # struct S;
892        /// # fn doc() -> S {
893        /// if return S {} {}
894        /// # unreachable!()
895        /// # }
896        ///
897        /// // parsed by rustc as:
898        /// //
899        /// //    if (return (S {})) {
900        /// //    }
901        /// //
902        /// // but could equally well have been this other arbitrary choice:
903        /// //
904        /// //    if (return S) {
905        /// //    }
906        /// //    {}
907        /// ```
908        ///
909        /// Note the grammar ambiguity on trailing braces is distinct from
910        /// precedence and is not captured by assigning a precedence level to
911        /// the braced struct init expr in relation to other operators. This can
912        /// be illustrated by `return 0..S {}` vs `match 0..S {}`. The former
913        /// parses as `return (0..(S {}))` implying tighter precedence for
914        /// struct init than `..`, while the latter parses as `match (0..S) {}`
915        /// implying tighter precedence for `..` than struct init, a
916        /// contradiction.
917        pub fn parse_without_eager_brace(input: ParseStream) -> Result<Term> {
918            ambiguous_term(input, AllowStruct(false))
919        }
920    }
921
922    impl Copy for AllowStruct {}
923
924    impl Clone for AllowStruct {
925        fn clone(&self) -> Self {
926            *self
927        }
928    }
929
930    impl Copy for Precedence {}
931
932    impl Clone for Precedence {
933        fn clone(&self) -> Self {
934            *self
935        }
936    }
937
938    impl PartialEq for Precedence {
939        fn eq(&self, other: &Self) -> bool {
940            *self as u8 == *other as u8
941        }
942    }
943
944    impl PartialOrd for Precedence {
945        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
946            let this = *self as u8;
947            let other = *other as u8;
948            Some(this.cmp(&other))
949        }
950    }
951
952    fn parse_term(
953        input: ParseStream,
954        mut lhs: Term,
955        allow_struct: AllowStruct,
956        base: Precedence,
957    ) -> Result<Term> {
958        loop {
959            if Precedence::Impl >= base && input.peek(Token![==]) && input.peek3(Token![>]) {
960                // a ==> b
961                let eqeq_token: Token![==] = input.parse()?;
962                let gt_token: Token![>] = input.parse()?;
963                let precedence = Precedence::Impl;
964                let mut rhs = unary_term(input, allow_struct)?;
965                loop {
966                    let next = peek_precedence(input);
967                    if next >= precedence {
968                        rhs = parse_term(input, rhs, allow_struct, next)?;
969                    } else {
970                        break;
971                    }
972                }
973                lhs = Term::Impl(TermImpl {
974                    hyp: Box::new(lhs),
975                    eqeq_token,
976                    gt_token,
977                    cons: Box::new(rhs),
978                });
979            } else if Precedence::Range >= base && input.peek(Token![..]) || input.peek(Token![..=])
980            {
981                let limits: RangeLimits = input.parse()?;
982                let precedence = Precedence::Range;
983                if input.is_empty() {
984                    if matches!(limits, RangeLimits::Closed(_)) {
985                        return Err(input.error("expected expression after ..="));
986                    }
987                    return Ok(Term::Range(TermRange { from: Some(lhs.into()), limits, to: None }));
988                }
989                let mut rhs = unary_term(input, allow_struct)?;
990                loop {
991                    let next = peek_precedence(input);
992                    if next >= precedence {
993                        rhs = parse_term(input, rhs, allow_struct, next)?;
994                    } else {
995                        break;
996                    }
997                }
998                lhs =
999                    Term::Range(TermRange { from: Some(lhs.into()), limits, to: Some(rhs.into()) })
1000            } else if input
1001                .fork()
1002                .parse::<BinOp>()
1003                .ok()
1004                .is_some_and(|op| Precedence::of(&op) >= base)
1005                && !(input.peek(Token![==]) && input.peek3(Token![>]))
1006            {
1007                let op: BinOp = input.parse()?;
1008                let precedence = Precedence::of(&op);
1009                let mut rhs = unary_term(input, allow_struct)?;
1010                loop {
1011                    let next = peek_precedence(input);
1012                    if next > precedence || next == precedence && precedence == Precedence::Assign {
1013                        rhs = parse_term(input, rhs, allow_struct, next)?;
1014                    } else {
1015                        break;
1016                    }
1017                }
1018                lhs = Term::Binary(TermBinary { left: Box::new(lhs), op, right: Box::new(rhs) });
1019            } else if Precedence::Cast >= base && input.peek(Token![as]) {
1020                let as_token: Token![as] = input.parse()?;
1021                let ty = input.call(Type::without_plus)?;
1022                lhs = Term::Cast(TermCast { expr: Box::new(lhs), as_token, ty: Box::new(ty) });
1023            } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1024                let colon_token: Token![:] = input.parse()?;
1025                let ty = input.call(Type::without_plus)?;
1026                lhs = Term::Type(TermType { expr: Box::new(lhs), colon_token, ty: Box::new(ty) });
1027            } else {
1028                break;
1029            }
1030        }
1031
1032        Ok(lhs)
1033    }
1034
1035    fn peek_precedence(input: ParseStream) -> Precedence {
1036        if input.peek(Token![==]) && input.peek3(Token![>]) {
1037            Precedence::Impl
1038        } else if let Ok(op) = input.fork().parse() {
1039            Precedence::of(&op)
1040        } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
1041            Precedence::Assign
1042        } else if input.peek(Token![..]) {
1043            Precedence::Range
1044        } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1045            Precedence::Cast
1046        } else {
1047            Precedence::Any
1048        }
1049    }
1050
1051    // Parse an arbitrary term.
1052    fn ambiguous_term(input: ParseStream, allow_struct: AllowStruct) -> Result<Term> {
1053        let lhs = unary_term(input, allow_struct)?;
1054        parse_term(input, lhs, allow_struct, Precedence::Any)
1055    }
1056
1057    fn unary_term(input: ParseStream, allow_struct: AllowStruct) -> Result<Term> {
1058        if input.peek(Token![&]) {
1059            Ok(Term::Reference(TermReference {
1060                and_token: input.parse()?,
1061                mutability: input.parse()?,
1062                expr: Box::new(unary_term(input, allow_struct)?),
1063            }))
1064        } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1065            // <UnOp> <trailer>
1066            Ok(Term::Unary(TermUnary {
1067                op: input.parse()?,
1068                expr: Box::new(unary_term(input, allow_struct)?),
1069            }))
1070        } else if input.peek(Token![^]) {
1071            // ^ <trailer>
1072            Ok(Term::Final(TermFinal {
1073                final_token: input.parse()?,
1074                term: Box::new(unary_term(input, allow_struct)?),
1075            }))
1076        } else {
1077            trailer_term(input, allow_struct)
1078        }
1079    }
1080
1081    // <atom> (..<args>) ...
1082    // <atom> . <ident> (..<args>) ...
1083    // <atom> . <ident> ...
1084    // <atom> . <lit> ...
1085    // <atom> [ <expr> ] ...
1086    // <atom> ? ...
1087    fn trailer_term(input: ParseStream, allow_struct: AllowStruct) -> Result<Term> {
1088        let atom = atom_term(input, allow_struct)?;
1089        let e = trailer_helper(input, atom)?;
1090        Ok(e)
1091    }
1092
1093    fn trailer_helper(input: ParseStream, mut e: Term) -> Result<Term> {
1094        loop {
1095            if input.peek(token::Paren) {
1096                let content;
1097                e = Term::Call(TermCall {
1098                    func: Box::new(e),
1099                    paren_token: parenthesized!(content in input),
1100                    args: content.parse_terminated(Term::parse, Token![,])?,
1101                });
1102            } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1103                let mut dot_token: Token![.] = input.parse()?;
1104
1105                let float_token: Option<LitFloat> = input.parse()?;
1106                if let Some(float_token) = float_token {
1107                    if multi_index(&mut e, &mut dot_token, float_token)? {
1108                        continue;
1109                    }
1110                }
1111
1112                let member: Member = input.parse()?;
1113                let turbofish = if matches!(member, Member::Named(_)) && input.peek(Token![::]) {
1114                    Some(TermMethodTurbofish {
1115                        colon2_token: input.parse()?,
1116                        lt_token: input.parse()?,
1117                        args: {
1118                            let mut args = Punctuated::new();
1119                            loop {
1120                                if input.peek(Token![>]) {
1121                                    break;
1122                                }
1123                                let value = input.call(generic_method_argument)?;
1124                                args.push_value(value);
1125                                if input.peek(Token![>]) {
1126                                    break;
1127                                }
1128                                let punct = input.parse()?;
1129                                args.push_punct(punct);
1130                            }
1131                            args
1132                        },
1133                        gt_token: input.parse()?,
1134                    })
1135                } else {
1136                    None
1137                };
1138
1139                if turbofish.is_some() || input.peek(token::Paren) {
1140                    if let Member::Named(method) = member {
1141                        let content;
1142                        e = Term::MethodCall(TermMethodCall {
1143                            receiver: Box::new(e),
1144                            dot_token,
1145                            method,
1146                            turbofish,
1147                            paren_token: parenthesized!(content in input),
1148                            args: content.parse_terminated(Term::parse, Token![,])?,
1149                        });
1150                        continue;
1151                    }
1152                }
1153
1154                e = Term::Field(TermField { base: Box::new(e), dot_token, member });
1155            } else if input.peek(token::Bracket) {
1156                let content;
1157                e = Term::Index(TermIndex {
1158                    expr: Box::new(e),
1159                    bracket_token: bracketed!(content in input),
1160                    index: content.parse()?,
1161                });
1162            } else if input.peek(Token![@]) {
1163                e = Term::View(TermView { term: Box::new(e), at_token: input.parse()? });
1164            } else {
1165                break;
1166            }
1167        }
1168        Ok(e)
1169    }
1170
1171    // Parse all atomic expressions which don't have to worry about precedence
1172    // interactions, as they are fully contained.
1173    fn atom_term(input: ParseStream, allow_struct: AllowStruct) -> Result<Term> {
1174        if input.peek(token::Group)
1175            && !input.peek2(Token![::])
1176            && !input.peek2(Token![!])
1177            && !input.peek2(token::Brace)
1178        {
1179            input.call(term_group).map(Term::Group)
1180        } else if input.peek(Lit) {
1181            input.parse().map(Term::Lit)
1182        } else if input.peek(Token![|]) {
1183            term_closure(input, allow_struct).map(Term::Closure)
1184        } else if (input.peek(Ident)
1185            && !(input.peek(kw::forall)
1186                || input.peek(kw::exists)
1187                || input.peek(kw::dead)
1188                || input.peek(kw::pearlite)))
1189            || input.peek(Token![::])
1190            || input.peek(Token![<])
1191            || input.peek(Token![self])
1192            || input.peek(Token![Self])
1193            || input.peek(Token![super])
1194            || input.peek(Token![crate])
1195        {
1196            path_or_macro_or_struct(input, allow_struct)
1197        } else if input.peek(token::Paren) {
1198            paren_or_tuple(input)
1199        } else if input.peek(token::Bracket) {
1200            array_or_repeat(input)
1201        } else if input.peek(Token![let]) {
1202            input.call(term_let).map(Term::Let)
1203        } else if input.peek(Token![if]) {
1204            input.parse().map(Term::If)
1205        } else if input.peek(kw::forall) || input.peek(kw::exists) {
1206            input.parse().map(Term::Quant)
1207        } else if input.peek(kw::dead) {
1208            input.parse().map(Term::Dead)
1209        } else if input.peek(kw::pearlite) {
1210            input.parse().map(Term::Pearlite)
1211        } else if input.peek(Token![match]) {
1212            input.parse().map(Term::Match)
1213        } else if input.peek(token::Brace) {
1214            input.call(term_block).map(Term::Block)
1215        } else if input.peek(Token![..]) {
1216            term_range(input, allow_struct).map(Term::Range)
1217        } else {
1218            Err(input.error("expected term"))
1219        }
1220    }
1221
1222    fn is_mod_style(p: &Path) -> bool {
1223        p.segments.iter().all(|segment| segment.arguments.is_none())
1224    }
1225
1226    fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Term> {
1227        let expr: TermPath = input.parse()?;
1228
1229        if expr.inner.qself.is_none()
1230            && input.peek(Token![!])
1231            && !input.peek(Token![!=])
1232            && is_mod_style(&expr.inner.path)
1233        {
1234            let bang_token: Token![!] = input.parse()?;
1235
1236            let (_, span_delim, tokens) = input.parse_any_delimiter()?;
1237
1238            // It's unclear what to do with macros. Either we translate the parameters, but then
1239            // it's impossible to handle proc macros whose parameters is not valid pearlite syntax,
1240            // or we don't translate parameters, but then we let the user write non-pearlite code
1241            // in pearlite... So we only treat well known macros.
1242
1243            if expr.inner.path.is_ident("proof_assert") {
1244                return Ok(Term::ProofAssert(TermProofAssert {
1245                    proof_assert_token: kw::proof_assert(expr.inner.span()),
1246                    bang_token,
1247                    block: TermBlock {
1248                        brace_token: token::Brace(span_delim),
1249                        stmts: TermBlock::parse_within(&tokens)?,
1250                    },
1251                }));
1252            } else if expr.inner.path.is_ident("pearlite") {
1253                return Ok(Term::Pearlite(TermPearlite {
1254                    pearlite_token: kw::pearlite(expr.inner.span()),
1255                    bang_token,
1256                    block: TermBlock {
1257                        brace_token: token::Brace(span_delim),
1258                        stmts: TermBlock::parse_within(&tokens)?,
1259                    },
1260                }));
1261            } else if expr.inner.path.is_ident("seq") {
1262                return Ok(Term::Seq(TermSeq {
1263                    seq_token: kw::seq(expr.inner.span()),
1264                    bang_token,
1265                    bracket_token: token::Bracket(span_delim),
1266                    terms: Punctuated::parse_terminated(&tokens)?,
1267                }));
1268            } else {
1269                return Err(Error::new_spanned(
1270                    expr,
1271                    " Unsupported expression: macros other than `pearlite!`, `proof_assert!` or `seq!` are unsupported in Pearlite code.",
1272                ));
1273            }
1274        }
1275
1276        if allow_struct.0 && input.peek(token::Brace) {
1277            term_struct_helper(input, expr.inner.path).map(Term::Struct)
1278        } else {
1279            Ok(Term::Path(expr))
1280        }
1281    }
1282
1283    fn paren_or_tuple(input: ParseStream) -> Result<Term> {
1284        let content;
1285        let paren_token = parenthesized!(content in input);
1286        if content.is_empty() {
1287            return Ok(Term::Tuple(TermTuple { paren_token, elems: Punctuated::new() }));
1288        }
1289
1290        let first: Term = content.parse()?;
1291        if content.is_empty() {
1292            return Ok(Term::Paren(TermParen { paren_token, expr: Box::new(first) }));
1293        }
1294
1295        let mut elems = Punctuated::new();
1296        elems.push_value(first);
1297        while !content.is_empty() {
1298            let punct = content.parse()?;
1299            elems.push_punct(punct);
1300            if content.is_empty() {
1301                break;
1302            }
1303            let value = content.parse()?;
1304            elems.push_value(value);
1305        }
1306        Ok(Term::Tuple(TermTuple { paren_token, elems }))
1307    }
1308
1309    fn array_or_repeat(input: ParseStream) -> Result<Term> {
1310        let content;
1311        let bracket_token = bracketed!(content in input);
1312        if content.is_empty() {
1313            return Ok(Term::Array(TermArray { bracket_token, elems: Punctuated::new() }));
1314        }
1315
1316        let first: Term = content.parse()?;
1317        if content.is_empty() || content.peek(Token![,]) {
1318            let mut elems = Punctuated::new();
1319            elems.push_value(first);
1320            while !content.is_empty() {
1321                let punct = content.parse()?;
1322                elems.push_punct(punct);
1323                if content.is_empty() {
1324                    break;
1325                }
1326                let value = content.parse()?;
1327                elems.push_value(value);
1328            }
1329            Ok(Term::Array(TermArray { bracket_token, elems }))
1330        } else if content.peek(Token![;]) {
1331            let semi_token: Token![;] = content.parse()?;
1332            let len: Term = content.parse()?;
1333            Ok(Term::Repeat(TermRepeat {
1334                bracket_token,
1335                expr: Box::new(first),
1336                semi_token,
1337                len: Box::new(len),
1338            }))
1339        } else {
1340            Err(content.error("expected `,` or `;`"))
1341        }
1342    }
1343
1344    pub(crate) fn term_early(input: ParseStream) -> Result<Term> {
1345        let mut expr = if input.peek(Token![if]) {
1346            Term::If(input.parse()?)
1347        } else if input.peek(Token![match]) {
1348            Term::Match(input.parse()?)
1349        } else if input.peek(token::Brace) {
1350            Term::Block(input.call(term_block)?)
1351        } else {
1352            let allow_struct = AllowStruct(true);
1353            let expr = unary_term(input, allow_struct)?;
1354
1355            return parse_term(input, expr, allow_struct, Precedence::Any);
1356        };
1357
1358        if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
1359            expr = trailer_helper(input, expr)?;
1360
1361            let allow_struct = AllowStruct(true);
1362            return parse_term(input, expr, allow_struct, Precedence::Any);
1363        }
1364
1365        Ok(expr)
1366    }
1367
1368    impl Parse for TermLit {
1369        fn parse(input: ParseStream) -> Result<Self> {
1370            Ok(TermLit { lit: input.parse()? })
1371        }
1372    }
1373
1374    fn term_group(input: ParseStream) -> Result<TermGroup> {
1375        input.parse_any_delimiter().and_then(|(delim, span, content)| {
1376            assert_eq!(delim, Delimiter::None);
1377            Ok(TermGroup { group_token: token::Group(span.join()), expr: content.parse()? })
1378        })
1379    }
1380
1381    fn generic_method_argument(input: ParseStream) -> Result<TermGenericMethodArgument> {
1382        if input.peek(Lit) {
1383            let lit = input.parse()?;
1384            return Ok(TermGenericMethodArgument::Const(Term::Lit(lit)));
1385        }
1386
1387        if input.peek(token::Brace) {
1388            let block = input.call(super::parsing::term_block)?;
1389            return Ok(TermGenericMethodArgument::Const(Term::Block(block)));
1390        }
1391
1392        input.parse().map(TermGenericMethodArgument::Type)
1393    }
1394
1395    fn term_let(input: ParseStream) -> Result<TermLet> {
1396        Ok(TermLet {
1397            let_token: input.parse()?,
1398            pat: Pat::parse_single(input)?,
1399            // pat: pat::parsing::multi_pat_with_leading_vert(input)?,
1400            eq_token: input.parse()?,
1401            expr: Box::new(input.call(Term::parse_without_eager_brace)?),
1402        })
1403    }
1404
1405    impl Parse for TermIf {
1406        fn parse(input: ParseStream) -> Result<Self> {
1407            Ok(TermIf {
1408                if_token: input.parse()?,
1409                cond: Box::new(input.call(Term::parse_without_eager_brace)?),
1410                then_branch: input.parse()?,
1411                else_branch: {
1412                    if input.peek(Token![else]) { Some(input.call(else_block)?) } else { None }
1413                },
1414            })
1415        }
1416    }
1417
1418    fn else_block(input: ParseStream) -> Result<(Token![else], Box<Term>)> {
1419        let else_token: Token![else] = input.parse()?;
1420
1421        let lookahead = input.lookahead1();
1422        let else_branch = if input.peek(Token![if]) {
1423            input.parse().map(Term::If)?
1424        } else if input.peek(token::Brace) {
1425            Term::Block(input.parse()?)
1426        } else {
1427            return Err(lookahead.error());
1428        };
1429
1430        Ok((else_token, Box::new(else_branch)))
1431    }
1432
1433    impl Parse for TermMatch {
1434        fn parse(input: ParseStream) -> Result<Self> {
1435            let match_token: Token![match] = input.parse()?;
1436            let expr = Term::parse_without_eager_brace(input)?;
1437
1438            let content;
1439            let brace_token = braced!(content in input);
1440
1441            let mut arms = Vec::new();
1442            while !content.is_empty() {
1443                arms.push(content.call(TermArm::parse)?);
1444            }
1445
1446            Ok(TermMatch { match_token, expr: Box::new(expr), brace_token, arms })
1447        }
1448    }
1449
1450    impl Parse for TermQuant {
1451        fn parse(input: ParseStream) -> Result<Self> {
1452            let quant_token = input.parse()?;
1453            let lt_token: Token![<] = input.parse()?;
1454
1455            let mut args = Punctuated::new();
1456            while !input.peek(Token![>]) {
1457                let quantarg = input.parse()?;
1458                args.push_value(quantarg);
1459                if input.peek(Token![>]) {
1460                    break;
1461                }
1462
1463                let punct = input.parse()?;
1464                args.push_punct(punct);
1465            }
1466
1467            let gt_token: Token![>] = input.parse()?;
1468
1469            let term = input.parse()?;
1470
1471            Ok(TermQuant { quant_token, lt_token, args, gt_token, term })
1472        }
1473    }
1474
1475    impl Parse for TermWithTriggers {
1476        fn parse(input: ParseStream) -> Result<Self> {
1477            let mut trigger = vec![];
1478
1479            while input.peek(Token![#]) {
1480                trigger.push(input.parse()?)
1481            }
1482
1483            let term = input.parse()?;
1484            Ok(TermWithTriggers { trigger, term })
1485        }
1486    }
1487
1488    impl Parse for EnsuresClosure {
1489        fn parse(input: ParseStream) -> Result<Self> {
1490            Ok(EnsuresClosure {
1491                or1_token: input.parse()?,
1492                result: Pat::parse_single(input)?,
1493                or2_token: input.parse()?,
1494                body: input.parse()?,
1495            })
1496        }
1497    }
1498
1499    impl Parse for EnsuresTerm {
1500        fn parse(input: ParseStream) -> Result<Self> {
1501            if input.peek(Token![|]) {
1502                Ok(EnsuresTerm::EnsuresClosure(input.parse()?))
1503            } else {
1504                Ok(EnsuresTerm::TermWithTriggers(input.parse()?))
1505            }
1506        }
1507    }
1508
1509    impl Parse for QuantToken {
1510        fn parse(input: ParseStream) -> Result<Self> {
1511            if input.peek(kw::forall) {
1512                Ok(QuantToken::Forall(input.parse()?))
1513            } else {
1514                Ok(QuantToken::Exists(input.parse()?))
1515            }
1516        }
1517    }
1518
1519    impl Parse for QuantArg {
1520        fn parse(input: ParseStream) -> Result<Self> {
1521            let ident = input.parse()?;
1522            if input.peek(Token![:]) {
1523                Ok(QuantArg { ident, ty: Some((input.parse()?, input.parse()?)) })
1524            } else {
1525                Ok(QuantArg { ident, ty: None })
1526            }
1527        }
1528    }
1529
1530    impl Parse for Trigger {
1531        fn parse(input: ParseStream) -> Result<Self> {
1532            let mut content;
1533            Ok(Trigger {
1534                pound_token: input.parse()?,
1535                bracket_token: bracketed!(content in input),
1536                trigger_token: content.parse()?,
1537                paren_token: parenthesized!(content in content),
1538                terms: Punctuated::parse_separated_nonempty(&content)?,
1539            })
1540        }
1541    }
1542
1543    impl Parse for TermDead {
1544        fn parse(input: ParseStream) -> Result<Self> {
1545            Ok(TermDead { dead_token: input.parse()? })
1546        }
1547    }
1548
1549    impl Parse for TermPearlite {
1550        fn parse(input: ParseStream) -> Result<Self> {
1551            Ok(TermPearlite {
1552                pearlite_token: input.parse()?,
1553                bang_token: input.parse()?,
1554                block: input.parse()?,
1555            })
1556        }
1557    }
1558
1559    macro_rules! impl_by_parsing_term {
1560        (
1561            $(
1562                $term_type:ty, $variant:ident, $msg:expr,
1563            )*
1564        ) => {
1565            $(
1566                #[cfg(all(feature = "full", feature = "printing"))]
1567                impl Parse for $term_type {
1568                    fn parse(input: ParseStream) -> Result<Self> {
1569                        let mut expr: Term = input.parse()?;
1570                        loop {
1571                            match expr {
1572                                Term::$variant(inner) => return Ok(inner),
1573                                Term::Group(next) => expr = *next.expr,
1574                                _ => return Err(Error::new_spanned(expr, $msg)),
1575                            }
1576                        }
1577                    }
1578                }
1579            )*
1580        };
1581    }
1582
1583    impl_by_parsing_term! {
1584        TermArray, Array, "expected slice literal term",
1585        TermCall, Call, "expected function call term",
1586        TermMethodCall, MethodCall, "expected method call term",
1587        TermTuple, Tuple, "expected tuple term",
1588        TermBinary, Binary, "expected binary operation",
1589        TermUnary, Unary, "expected unary operation",
1590        TermCast, Cast, "expected cast term",
1591        TermType, Type, "expected type ascription term",
1592        TermLet, Let, "expected let guard",
1593        TermField, Field, "expected struct field access",
1594        TermIndex, Index, "expected indexing term",
1595        TermRange, Range, "expected range term",
1596        TermReference, Reference, "expected reference term",
1597        TermStruct, Struct, "expected struct literal term",
1598        TermRepeat, Repeat, "expected array literal constructed from one repeated element",
1599        TermParen, Paren, "expected parenthesized term",
1600    }
1601
1602    impl Parse for TermFieldValue {
1603        fn parse(input: ParseStream) -> Result<Self> {
1604            let member: Member = input.parse()?;
1605            let (colon_token, value) =
1606                if input.peek(Token![:]) || !matches!(member, Member::Named(_)) {
1607                    let colon_token: Token![:] = input.parse()?;
1608                    let value: Term = input.parse()?;
1609                    (Some(colon_token), value)
1610                } else if let Member::Named(ident) = &member {
1611                    let value = Term::Path(TermPath {
1612                        inner: ExprPath {
1613                            qself: None,
1614                            path: Path::from(ident.clone()),
1615                            attrs: Vec::new(),
1616                        },
1617                    });
1618                    (None, value)
1619                } else {
1620                    unreachable!()
1621                };
1622
1623            Ok(TermFieldValue { member, colon_token, expr: value })
1624        }
1625    }
1626
1627    fn term_struct_helper(input: ParseStream, path: Path) -> Result<TermStruct> {
1628        let content;
1629        let brace_token = braced!(content in input);
1630
1631        let mut fields = Punctuated::new();
1632        while !content.is_empty() {
1633            if content.peek(Token![..]) {
1634                return Ok(TermStruct {
1635                    brace_token,
1636                    path,
1637                    fields,
1638                    dot2_token: Some(content.parse()?),
1639                    rest: Some(Box::new(content.parse()?)),
1640                });
1641            }
1642
1643            fields.push(content.parse()?);
1644            if content.is_empty() {
1645                break;
1646            }
1647            let punct: Token![,] = content.parse()?;
1648            fields.push_punct(punct);
1649        }
1650
1651        Ok(TermStruct { brace_token, path, fields, dot2_token: None, rest: None })
1652    }
1653
1654    pub fn term_block(input: ParseStream) -> Result<TermBlock> {
1655        let content;
1656        let brace_token = braced!(content in input);
1657        let stmts = content.call(TermBlock::parse_within)?;
1658
1659        Ok(TermBlock { brace_token, stmts })
1660    }
1661
1662    fn term_range(input: ParseStream, allow_struct: AllowStruct) -> Result<TermRange> {
1663        Ok(TermRange {
1664            from: None,
1665            limits: input.parse()?,
1666            to: {
1667                if input.is_empty()
1668                    || input.peek(Token![,])
1669                    || input.peek(Token![;])
1670                    || !allow_struct.0 && input.peek(token::Brace)
1671                {
1672                    None
1673                } else {
1674                    let to = ambiguous_term(input, allow_struct)?;
1675                    Some(Box::new(to))
1676                }
1677            },
1678        })
1679    }
1680
1681    impl Parse for TermPath {
1682        fn parse(input: ParseStream) -> Result<Self> {
1683            let exp_path: ExprPath = input.parse()?;
1684
1685            // let (qself, path) = syn::path::parsing::qpath(input, true)?;
1686            // Ok(TermPath { qself: exp_path.qself, path: exp_path.path })
1687            Ok(TermPath { inner: exp_path })
1688        }
1689    }
1690
1691    impl Parse for TermArm {
1692        fn parse(input: ParseStream) -> Result<TermArm> {
1693            let requires_comma;
1694            Ok(TermArm {
1695                pat: Pat::parse_multi_with_leading_vert(input)?,
1696                guard: {
1697                    if input.peek(Token![if]) {
1698                        let if_token: Token![if] = input.parse()?;
1699                        let guard: Term = input.parse()?;
1700                        Some((if_token, Box::new(guard)))
1701                    } else {
1702                        None
1703                    }
1704                },
1705                fat_arrow_token: input.parse()?,
1706                body: {
1707                    let body = input.call(term_early)?;
1708                    requires_comma = requires_terminator(&body);
1709                    Box::new(body)
1710                },
1711                comma: {
1712                    if requires_comma && !input.is_empty() {
1713                        Some(input.parse()?)
1714                    } else {
1715                        input.parse()?
1716                    }
1717                },
1718            })
1719        }
1720    }
1721
1722    impl Parse for super::Index {
1723        fn parse(input: ParseStream) -> Result<Self> {
1724            let lit: LitInt = input.parse()?;
1725            if lit.suffix().is_empty() {
1726                Ok(super::Index {
1727                    index: lit
1728                        .base10_digits()
1729                        .parse()
1730                        .map_err(|err| Error::new(lit.span(), err))?,
1731                    span: lit.span(),
1732                })
1733            } else {
1734                Err(Error::new(lit.span(), "expected unsuffixed integer"))
1735            }
1736        }
1737    }
1738
1739    fn multi_index(e: &mut Term, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
1740        let mut float_repr = float.to_string();
1741        let trailing_dot = float_repr.ends_with('.');
1742        if trailing_dot {
1743            float_repr.truncate(float_repr.len() - 1);
1744        }
1745        for part in float_repr.split('.') {
1746            let index = syn::parse_str(part).map_err(|err| Error::new(float.span(), err))?;
1747            let base = mem::replace(e, Term::__Nonexhaustive);
1748            *e = Term::Field(TermField {
1749                base: Box::new(base),
1750                dot_token: Token![.](dot_token.span),
1751                member: Member::Unnamed(index),
1752            });
1753            *dot_token = Token![.](float.span());
1754        }
1755        Ok(!trailing_dot)
1756    }
1757
1758    fn term_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<TermClosure> {
1759        let or1_token: Token![|] = input.parse()?;
1760
1761        let mut inputs = Punctuated::new();
1762        loop {
1763            if input.peek(Token![|]) {
1764                break;
1765            }
1766            let value = closure_arg(input)?;
1767            inputs.push_value(value);
1768            if input.peek(Token![|]) {
1769                break;
1770            }
1771            let punct: Token![,] = input.parse()?;
1772            inputs.push_punct(punct);
1773        }
1774
1775        let or2_token: Token![|] = input.parse()?;
1776
1777        let (output, body) = if input.peek(Token![->]) {
1778            let arrow_token: Token![->] = input.parse()?;
1779            let ty: Type = input.parse()?;
1780            let body: TermBlock = input.parse()?;
1781            let output = ReturnType::Type(arrow_token, Box::new(ty));
1782            let block = Term::Block(body);
1783            (output, block)
1784        } else {
1785            let body = ambiguous_term(input, allow_struct)?;
1786            (ReturnType::Default, body)
1787        };
1788
1789        Ok(TermClosure {
1790            attrs: Vec::new(),
1791            or1_token,
1792            inputs,
1793            or2_token,
1794            output,
1795            body: Box::new(body),
1796        })
1797    }
1798
1799    fn closure_arg(input: ParseStream) -> Result<Pat> {
1800        let attrs = input.call(Attribute::parse_outer)?;
1801        let mut pat = Pat::parse_single(input)?;
1802
1803        if input.peek(Token![:]) {
1804            Ok(Pat::Type(PatType {
1805                attrs,
1806                pat: Box::new(pat),
1807                colon_token: input.parse()?,
1808                ty: input.parse()?,
1809            }))
1810        } else {
1811            match &mut pat {
1812                Pat::Const(pat) => pat.attrs = attrs,
1813                Pat::Ident(pat) => pat.attrs = attrs,
1814                Pat::Lit(pat) => pat.attrs = attrs,
1815                Pat::Macro(pat) => pat.attrs = attrs,
1816                Pat::Or(pat) => pat.attrs = attrs,
1817                Pat::Paren(pat) => pat.attrs = attrs,
1818                Pat::Path(pat) => pat.attrs = attrs,
1819                Pat::Range(pat) => pat.attrs = attrs,
1820                Pat::Reference(pat) => pat.attrs = attrs,
1821                Pat::Rest(pat) => pat.attrs = attrs,
1822                Pat::Slice(pat) => pat.attrs = attrs,
1823                Pat::Struct(pat) => pat.attrs = attrs,
1824                Pat::Tuple(pat) => pat.attrs = attrs,
1825                Pat::TupleStruct(pat) => pat.attrs = attrs,
1826                Pat::Wild(pat) => pat.attrs = attrs,
1827                Pat::Type(_) => unreachable!(),
1828                Pat::Verbatim(_) => {}
1829                _ => unimplemented!(),
1830            }
1831            Ok(pat)
1832        }
1833    }
1834}
1835
1836#[cfg(feature = "printing")]
1837pub(crate) mod printing {
1838    use super::*;
1839    use crate::print::TokensOrDefault;
1840    use proc_macro2::{Literal, TokenStream};
1841    use quote::{ToTokens, TokenStreamExt};
1842
1843    // If the given term is a bare `TermStruct`, wraps it in parenthesis
1844    // before appending it to `TokenStream`.
1845    fn wrap_bare_struct(tokens: &mut TokenStream, e: &Term) {
1846        if let Term::Struct(_) = *e {
1847            token::Paren::default().surround(tokens, |tokens| {
1848                e.to_tokens(tokens);
1849            });
1850        } else {
1851            e.to_tokens(tokens);
1852        }
1853    }
1854
1855    impl ToTokens for TermBlock {
1856        fn to_tokens(&self, tokens: &mut TokenStream) {
1857            self.brace_token.surround(tokens, |tokens| {
1858                tokens.append_all(&self.stmts);
1859            });
1860        }
1861    }
1862
1863    impl ToTokens for TermStmt {
1864        fn to_tokens(&self, tokens: &mut TokenStream) {
1865            match self {
1866                TermStmt::Local(local) => local.to_tokens(tokens),
1867                TermStmt::Expr(expr) => expr.to_tokens(tokens),
1868                TermStmt::Semi(expr, semi) => {
1869                    expr.to_tokens(tokens);
1870                    semi.to_tokens(tokens);
1871                }
1872                TermStmt::Item(i) => i.to_tokens(tokens),
1873                TermStmt::Empty(semi) => semi.to_tokens(tokens),
1874            }
1875        }
1876    }
1877
1878    impl ToTokens for TLocal {
1879        fn to_tokens(&self, tokens: &mut TokenStream) {
1880            self.let_token.to_tokens(tokens);
1881            self.pat.to_tokens(tokens);
1882            if let Some((eq_token, init)) = &self.init {
1883                eq_token.to_tokens(tokens);
1884                init.to_tokens(tokens);
1885            }
1886            self.semi_token.to_tokens(tokens);
1887        }
1888    }
1889
1890    impl ToTokens for TermArray {
1891        fn to_tokens(&self, tokens: &mut TokenStream) {
1892            self.bracket_token.surround(tokens, |tokens| {
1893                self.elems.to_tokens(tokens);
1894            })
1895        }
1896    }
1897
1898    impl ToTokens for TermCall {
1899        fn to_tokens(&self, tokens: &mut TokenStream) {
1900            self.func.to_tokens(tokens);
1901            self.paren_token.surround(tokens, |tokens| {
1902                self.args.to_tokens(tokens);
1903            })
1904        }
1905    }
1906
1907    impl ToTokens for TermMethodCall {
1908        fn to_tokens(&self, tokens: &mut TokenStream) {
1909            self.receiver.to_tokens(tokens);
1910            self.dot_token.to_tokens(tokens);
1911            self.method.to_tokens(tokens);
1912            self.turbofish.to_tokens(tokens);
1913            self.paren_token.surround(tokens, |tokens| {
1914                self.args.to_tokens(tokens);
1915            });
1916        }
1917    }
1918
1919    impl ToTokens for TermClosure {
1920        fn to_tokens(&self, tokens: &mut TokenStream) {
1921            tokens.append_all(&self.attrs);
1922            self.or1_token.to_tokens(tokens);
1923            self.inputs.to_tokens(tokens);
1924            self.or2_token.to_tokens(tokens);
1925            self.output.to_tokens(tokens);
1926            self.body.to_tokens(tokens);
1927        }
1928    }
1929
1930    impl ToTokens for TermMethodTurbofish {
1931        fn to_tokens(&self, tokens: &mut TokenStream) {
1932            self.colon2_token.to_tokens(tokens);
1933            self.lt_token.to_tokens(tokens);
1934            self.args.to_tokens(tokens);
1935            self.gt_token.to_tokens(tokens);
1936        }
1937    }
1938
1939    impl ToTokens for TermGenericMethodArgument {
1940        fn to_tokens(&self, tokens: &mut TokenStream) {
1941            match self {
1942                TermGenericMethodArgument::Type(t) => t.to_tokens(tokens),
1943                TermGenericMethodArgument::Const(c) => c.to_tokens(tokens),
1944            }
1945        }
1946    }
1947
1948    impl ToTokens for TermTuple {
1949        fn to_tokens(&self, tokens: &mut TokenStream) {
1950            self.paren_token.surround(tokens, |tokens| {
1951                self.elems.to_tokens(tokens);
1952                // If we only have one argument, we need a trailing comma to
1953                // distinguish TermTuple from TermParen.
1954                if self.elems.len() == 1 && !self.elems.trailing_punct() {
1955                    <Token![,]>::default().to_tokens(tokens);
1956                }
1957            })
1958        }
1959    }
1960
1961    impl ToTokens for TermBinary {
1962        fn to_tokens(&self, tokens: &mut TokenStream) {
1963            self.left.to_tokens(tokens);
1964            self.op.to_tokens(tokens);
1965            self.right.to_tokens(tokens);
1966        }
1967    }
1968
1969    impl ToTokens for TermUnary {
1970        fn to_tokens(&self, tokens: &mut TokenStream) {
1971            self.op.to_tokens(tokens);
1972            self.expr.to_tokens(tokens);
1973        }
1974    }
1975
1976    impl ToTokens for TermFinal {
1977        fn to_tokens(&self, tokens: &mut TokenStream) {
1978            self.final_token.to_tokens(tokens);
1979            self.term.to_tokens(tokens);
1980        }
1981    }
1982
1983    impl ToTokens for TermView {
1984        fn to_tokens(&self, tokens: &mut TokenStream) {
1985            self.term.to_tokens(tokens);
1986            self.at_token.to_tokens(tokens);
1987        }
1988    }
1989
1990    impl ToTokens for TermLit {
1991        fn to_tokens(&self, tokens: &mut TokenStream) {
1992            self.lit.to_tokens(tokens);
1993        }
1994    }
1995
1996    impl ToTokens for TermCast {
1997        fn to_tokens(&self, tokens: &mut TokenStream) {
1998            self.expr.to_tokens(tokens);
1999            self.as_token.to_tokens(tokens);
2000            self.ty.to_tokens(tokens);
2001        }
2002    }
2003
2004    impl ToTokens for TermType {
2005        fn to_tokens(&self, tokens: &mut TokenStream) {
2006            self.expr.to_tokens(tokens);
2007            self.colon_token.to_tokens(tokens);
2008            self.ty.to_tokens(tokens);
2009        }
2010    }
2011
2012    impl ToTokens for TermImpl {
2013        fn to_tokens(&self, tokens: &mut TokenStream) {
2014            self.hyp.to_tokens(tokens);
2015            self.eqeq_token.to_tokens(tokens);
2016            self.gt_token.to_tokens(tokens);
2017            self.cons.to_tokens(tokens);
2018        }
2019    }
2020
2021    impl ToTokens for TermQuant {
2022        fn to_tokens(&self, tokens: &mut TokenStream) {
2023            self.quant_token.to_tokens(tokens);
2024            self.lt_token.to_tokens(tokens);
2025            for input in self.args.pairs() {
2026                input.to_tokens(tokens);
2027            }
2028            self.gt_token.to_tokens(tokens);
2029            self.term.to_tokens(tokens);
2030        }
2031    }
2032
2033    impl ToTokens for TermWithTriggers {
2034        fn to_tokens(&self, tokens: &mut TokenStream) {
2035            for trigger in self.trigger.iter() {
2036                trigger.to_tokens(tokens);
2037            }
2038            self.term.to_tokens(tokens);
2039        }
2040    }
2041
2042    impl ToTokens for EnsuresClosure {
2043        fn to_tokens(&self, tokens: &mut TokenStream) {
2044            self.or1_token.to_tokens(tokens);
2045            self.result.to_tokens(tokens);
2046            self.or2_token.to_tokens(tokens);
2047            self.body.to_tokens(tokens);
2048        }
2049    }
2050
2051    impl ToTokens for QuantArg {
2052        fn to_tokens(&self, tokens: &mut TokenStream) {
2053            self.ident.to_tokens(tokens);
2054            if let Some((colon_token, ty)) = &self.ty {
2055                colon_token.to_tokens(tokens);
2056                ty.to_tokens(tokens);
2057            }
2058        }
2059    }
2060
2061    impl ToTokens for Trigger {
2062        fn to_tokens(&self, tokens: &mut TokenStream) {
2063            self.pound_token.to_tokens(tokens);
2064            self.bracket_token.surround(tokens, |tokens| {
2065                self.trigger_token.to_tokens(tokens);
2066                self.paren_token.surround(tokens, |tokens| {
2067                    self.terms.to_tokens(tokens);
2068                    if !self.terms.empty_or_trailing() {
2069                        <Token![,] as Default>::default().to_tokens(tokens)
2070                    }
2071                })
2072            })
2073        }
2074    }
2075
2076    impl ToTokens for TermDead {
2077        fn to_tokens(&self, tokens: &mut TokenStream) {
2078            self.dead_token.to_tokens(tokens);
2079        }
2080    }
2081
2082    impl ToTokens for TermPearlite {
2083        fn to_tokens(&self, tokens: &mut TokenStream) {
2084            self.pearlite_token.to_tokens(tokens);
2085            self.bang_token.to_tokens(tokens);
2086            self.block.to_tokens(tokens);
2087        }
2088    }
2089
2090    impl ToTokens for TermProofAssert {
2091        fn to_tokens(&self, tokens: &mut TokenStream) {
2092            self.proof_assert_token.to_tokens(tokens);
2093            self.bang_token.to_tokens(tokens);
2094            self.block.to_tokens(tokens);
2095        }
2096    }
2097
2098    impl ToTokens for TermSeq {
2099        fn to_tokens(&self, tokens: &mut TokenStream) {
2100            self.seq_token.to_tokens(tokens);
2101            self.bang_token.to_tokens(tokens);
2102            self.bracket_token.surround(tokens, |tokens| self.terms.to_tokens(tokens));
2103        }
2104    }
2105
2106    fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Term>)>) {
2107        if let Some((else_token, else_)) = else_ {
2108            else_token.to_tokens(tokens);
2109
2110            // If we are not one of the valid expressions to exist in an else
2111            // clause, wrap ourselves in a block.
2112            match **else_ {
2113                Term::If(_) | Term::Block(_) => {
2114                    else_.to_tokens(tokens);
2115                }
2116                _ => {
2117                    token::Brace::default().surround(tokens, |tokens| {
2118                        else_.to_tokens(tokens);
2119                    });
2120                }
2121            }
2122        }
2123    }
2124
2125    impl ToTokens for TermLet {
2126        fn to_tokens(&self, tokens: &mut TokenStream) {
2127            self.let_token.to_tokens(tokens);
2128            self.pat.to_tokens(tokens);
2129            self.eq_token.to_tokens(tokens);
2130            wrap_bare_struct(tokens, &self.expr);
2131        }
2132    }
2133
2134    impl ToTokens for TermIf {
2135        fn to_tokens(&self, tokens: &mut TokenStream) {
2136            self.if_token.to_tokens(tokens);
2137            wrap_bare_struct(tokens, &self.cond);
2138            self.then_branch.to_tokens(tokens);
2139            maybe_wrap_else(tokens, &self.else_branch);
2140        }
2141    }
2142
2143    impl ToTokens for TermMatch {
2144        fn to_tokens(&self, tokens: &mut TokenStream) {
2145            self.match_token.to_tokens(tokens);
2146            wrap_bare_struct(tokens, &self.expr);
2147            self.brace_token.surround(tokens, |tokens| {
2148                for (i, arm) in self.arms.iter().enumerate() {
2149                    arm.to_tokens(tokens);
2150                    // Ensure that we have a comma after a non-block arm, except
2151                    // for the last one.
2152                    let is_last = i == self.arms.len() - 1;
2153                    if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
2154                        <Token![,]>::default().to_tokens(tokens);
2155                    }
2156                }
2157            });
2158        }
2159    }
2160
2161    impl ToTokens for TermField {
2162        fn to_tokens(&self, tokens: &mut TokenStream) {
2163            self.base.to_tokens(tokens);
2164            self.dot_token.to_tokens(tokens);
2165            self.member.to_tokens(tokens);
2166        }
2167    }
2168
2169    // TODO: Figure out why rust thinks this is form syn
2170    impl ToTokens for super::Index {
2171        fn to_tokens(&self, tokens: &mut TokenStream) {
2172            let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
2173            lit.set_span(self.span);
2174            tokens.append(lit);
2175        }
2176    }
2177
2178    impl ToTokens for TermIndex {
2179        fn to_tokens(&self, tokens: &mut TokenStream) {
2180            self.expr.to_tokens(tokens);
2181            self.bracket_token.surround(tokens, |tokens| {
2182                self.index.to_tokens(tokens);
2183            });
2184        }
2185    }
2186
2187    impl ToTokens for TermRange {
2188        fn to_tokens(&self, tokens: &mut TokenStream) {
2189            self.from.to_tokens(tokens);
2190            match &self.limits {
2191                RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
2192                RangeLimits::Closed(t) => t.to_tokens(tokens),
2193            }
2194            self.to.to_tokens(tokens);
2195        }
2196    }
2197
2198    impl ToTokens for TermReference {
2199        fn to_tokens(&self, tokens: &mut TokenStream) {
2200            self.and_token.to_tokens(tokens);
2201            self.mutability.to_tokens(tokens);
2202            self.expr.to_tokens(tokens);
2203        }
2204    }
2205
2206    impl ToTokens for TermPath {
2207        fn to_tokens(&self, tokens: &mut TokenStream) {
2208            self.inner.to_tokens(tokens)
2209            // private::print_path(tokens, &self.qself, &self.path);
2210        }
2211    }
2212
2213    impl ToTokens for TermStruct {
2214        fn to_tokens(&self, tokens: &mut TokenStream) {
2215            self.path.to_tokens(tokens);
2216            self.brace_token.surround(tokens, |tokens| {
2217                self.fields.to_tokens(tokens);
2218                if self.rest.is_some() {
2219                    TokensOrDefault(&self.dot2_token).to_tokens(tokens);
2220                    self.rest.to_tokens(tokens);
2221                }
2222            })
2223        }
2224    }
2225
2226    impl ToTokens for TermRepeat {
2227        fn to_tokens(&self, tokens: &mut TokenStream) {
2228            self.bracket_token.surround(tokens, |tokens| {
2229                self.expr.to_tokens(tokens);
2230                self.semi_token.to_tokens(tokens);
2231                self.len.to_tokens(tokens);
2232            })
2233        }
2234    }
2235
2236    impl ToTokens for TermGroup {
2237        fn to_tokens(&self, tokens: &mut TokenStream) {
2238            self.group_token.surround(tokens, |tokens| {
2239                self.expr.to_tokens(tokens);
2240            });
2241        }
2242    }
2243
2244    impl ToTokens for TermParen {
2245        fn to_tokens(&self, tokens: &mut TokenStream) {
2246            self.paren_token.surround(tokens, |tokens| {
2247                self.expr.to_tokens(tokens);
2248            });
2249        }
2250    }
2251
2252    impl ToTokens for TermFieldValue {
2253        fn to_tokens(&self, tokens: &mut TokenStream) {
2254            self.member.to_tokens(tokens);
2255            if let Some(colon_token) = &self.colon_token {
2256                colon_token.to_tokens(tokens);
2257                self.expr.to_tokens(tokens);
2258            }
2259        }
2260    }
2261
2262    impl ToTokens for TermArm {
2263        fn to_tokens(&self, tokens: &mut TokenStream) {
2264            self.pat.to_tokens(tokens);
2265            if let Some((if_token, guard)) = &self.guard {
2266                if_token.to_tokens(tokens);
2267                guard.to_tokens(tokens);
2268            }
2269            self.fat_arrow_token.to_tokens(tokens);
2270            self.body.to_tokens(tokens);
2271            self.comma.to_tokens(tokens);
2272        }
2273    }
2274}