Skip to main content

flux_syntax/parser/
mod.rs

1pub(crate) mod lookahead;
2mod utils;
3use std::{collections::HashSet, str::FromStr, vec};
4
5use lookahead::{AnyLit, LAngle, NonReserved, RAngle};
6use rustc_ast::token::Lit;
7use rustc_data_structures::unord::UnordSet;
8use rustc_span::{Symbol, sym::Output};
9use utils::{
10    angle, braces, brackets, delimited, opt_angle, parens, punctuated_until,
11    punctuated_with_trailing, repeat_while, sep1, until,
12};
13
14use crate::{
15    ParseCtxt, ParseError, ParseResult,
16    parser::lookahead::{AnyOf, Expected, PeekExpected},
17    surface::{
18        self, Async,
19        Attr::{self},
20        BaseSort, BaseTy, BaseTyKind, BinOp, BindKind, ConstArg, ConstArgKind, ConstructorArg,
21        DetachedInherentImpl, DetachedItem, DetachedItemKind, DetachedSpecs, DetachedTrait,
22        DetachedTraitImpl, Ensures, EnumDef, Expr, ExprKind, ExprPath, ExprPathSegment, FieldExpr,
23        FluxItem, FnInput, FnOutput, FnRetTy, FnSig, GenericArg, GenericArgKind, GenericBounds,
24        GenericParam, Generics, Ident, ImplAssocReft, Indices, LetDecl, LitKind, Mutability,
25        ParamMode, Path, PathSegment, PrimOpProp, Qualifier, QualifierKind, QuantKind, RefineArg,
26        RefineParam, RefineParams, Requires, Sort, SortDecl, SortPath, SpecFunc, Spread,
27        StaticInfo, StructDef, TraitAssocReft, TraitRef, Trusted, Ty, TyAlias, TyKind, UnOp,
28        UseTree, UseTreeKind, VariantDef, VariantRet, WhereBoundPredicate,
29    },
30    symbols::{kw, sym},
31    token::{self, Comma, Delimiter::*, IdentIsRaw, Or, Token, TokenKind},
32};
33
34/// An attribute that's considered part of the *syntax* of an item.
35///
36/// This is in contrast to a [`surface::Attr`] which changes the behavior of an item. For example,
37/// a `#[refined_by(...)]` is part of the syntax of an adt: we could think of a different syntax
38/// that doesn't use an attribute. The existence of a syntax attribute in the token stream can be
39/// used to decide how to keep parsing, for example, if we see a `#[reft]` we know that the next
40/// item must be an associated refinement and not a method inside an impl or trait.
41enum SyntaxAttr {
42    /// A `#[reft]` attribute
43    Reft,
44    /// A `#[invariant]` attribute
45    Invariant(Expr),
46    /// A `#[refined_by(...)]` attribute
47    RefinedBy(RefineParams),
48    /// A `#[hide]` attribute
49    ///
50    /// NOTE(nilehmann) This should be considered a normal attribute, but we haven't implemented
51    /// attributes for flux items. If we start seeing more of these we should consider implementing
52    /// the infrastructure necesary to keep a list of attributes inside the flux item like we do
53    /// for rust items.
54    Hide,
55    /// a `#[opaque]` attribute
56    Opaque,
57    /// A `#[no_panic_if(...)]` attribute
58    NoPanicIf(Expr),
59}
60
61#[derive(Default)]
62struct ParsedAttrs {
63    normal: Vec<Attr>,
64    syntax: Vec<SyntaxAttr>,
65}
66
67impl ParsedAttrs {
68    fn is_reft(&self) -> bool {
69        self.syntax
70            .iter()
71            .any(|attr| matches!(attr, SyntaxAttr::Reft))
72    }
73
74    fn is_hide(&self) -> bool {
75        self.syntax
76            .iter()
77            .any(|attr| matches!(attr, SyntaxAttr::Hide))
78    }
79
80    fn is_opaque(&self) -> bool {
81        self.syntax
82            .iter()
83            .any(|attr| matches!(attr, SyntaxAttr::Opaque))
84    }
85
86    fn refined_by(&mut self) -> Option<RefineParams> {
87        let pos = self
88            .syntax
89            .iter()
90            .position(|x| matches!(x, SyntaxAttr::RefinedBy(_)))?;
91        if let SyntaxAttr::RefinedBy(params) = self.syntax.remove(pos) {
92            Some(params)
93        } else {
94            None
95        }
96    }
97
98    fn no_panic_if(&mut self) -> Option<Expr> {
99        let pos = self
100            .syntax
101            .iter()
102            .position(|x| matches!(x, SyntaxAttr::NoPanicIf(_)))?;
103        if let SyntaxAttr::NoPanicIf(expr) = self.syntax.remove(pos) { Some(expr) } else { None }
104    }
105
106    fn invariant(&mut self) -> Option<Expr> {
107        let pos = self
108            .syntax
109            .iter()
110            .position(|x| matches!(x, SyntaxAttr::Invariant(_)))?;
111        if let SyntaxAttr::Invariant(exp) = self.syntax.remove(pos) { Some(exp) } else { None }
112    }
113}
114
115/// ```text
116///   yes ⟨ , reason = ⟨literal⟩ ⟩?
117/// | no ⟨ , reason = ⟨literal⟩ ⟩?
118/// | reason = ⟨literal⟩
119/// ```
120pub(crate) fn parse_yes_or_no_with_reason(cx: &mut ParseCtxt) -> ParseResult<bool> {
121    let mut lookahead = cx.lookahead1();
122    if lookahead.advance_if(sym::yes) {
123        if cx.advance_if(token::Comma) {
124            parse_reason(cx)?;
125        }
126        Ok(true)
127    } else if lookahead.advance_if(sym::no) {
128        if cx.advance_if(token::Comma) {
129            parse_reason(cx)?;
130        }
131        Ok(false)
132    } else if lookahead.peek(sym::reason) {
133        parse_reason(cx)?;
134        Ok(true)
135    } else {
136        Err(lookahead.into_error())
137    }
138}
139
140/// ```text
141/// ⟨reason⟩ := reason = ⟨literal⟩
142/// ```
143fn parse_reason(cx: &mut ParseCtxt) -> ParseResult {
144    cx.expect(sym::reason)?;
145    cx.expect(token::Eq)?;
146    cx.expect(AnyLit)
147}
148
149/// ```text
150/// ⟨ident_list⟩ := ⟨ident⟩,*
151/// ```
152pub(crate) fn parse_ident_list(cx: &mut ParseCtxt) -> ParseResult<Vec<Ident>> {
153    punctuated_until(cx, Comma, token::Eof, parse_ident)
154}
155
156/// ```text
157/// ⟨flux_items⟩ := ⟨flux_item⟩*
158/// ```
159pub(crate) fn parse_flux_items(cx: &mut ParseCtxt) -> ParseResult<Vec<FluxItem>> {
160    until(cx, token::Eof, parse_flux_item)
161}
162
163/// ```text
164/// ⟨flux_item⟩ := ⟨func_def⟩
165///              | ⟨qualifier⟩
166///              | ⟨sort_decl⟩
167///              | ⟨primop_prop⟩
168///              | ⟨use_item⟩
169/// ```
170fn parse_flux_item(cx: &mut ParseCtxt) -> ParseResult<FluxItem> {
171    let mut lookahead = cx.lookahead1();
172    if lookahead.peek(token::Pound) || lookahead.peek(kw::Fn) {
173        parse_reft_func(cx).map(FluxItem::FuncDef)
174    } else if lookahead.peek(kw::Local)
175        || lookahead.peek(kw::Invariant)
176        || lookahead.peek(kw::Qualifier)
177    {
178        parse_qualifier(cx).map(FluxItem::Qualifier)
179    } else if lookahead.peek(kw::Opaque) {
180        parse_sort_decl(cx).map(FluxItem::SortDecl)
181    } else if lookahead.peek(kw::Property) {
182        parse_primop_property(cx).map(FluxItem::PrimOpProp)
183    } else if lookahead.peek(kw::Use) {
184        parse_use_item(cx).map(FluxItem::Use)
185    } else {
186        Err(lookahead.into_error())
187    }
188}
189
190///```text
191/// ⟨specs⟩ ::= ⟨specs⟩*
192/// ```
193pub(crate) fn parse_detached_specs(cx: &mut ParseCtxt) -> ParseResult<surface::DetachedSpecs> {
194    let items = until(cx, token::Eof, parse_detached_item)?;
195    Ok(surface::DetachedSpecs { items })
196}
197
198///```text
199/// ⟨specs⟩ ::= ⟨fn-spec⟩
200///           | ⟨struct-spec⟩
201///           | ⟨enum-spec⟩
202///           | ⟨mod⟩
203///           | ⟨impl⟩
204/// ```
205pub(crate) fn parse_detached_item(cx: &mut ParseCtxt) -> ParseResult<DetachedItem> {
206    let attrs = parse_attrs(cx)?;
207    let mut lookahead = cx.lookahead1();
208    if lookahead.peek(kw::Fn) {
209        Ok(parse_detached_fn_sig(cx, attrs)?.map_kind(DetachedItemKind::FnSig))
210    } else if lookahead.peek(kw::Mod) {
211        parse_detached_mod(cx)
212    } else if lookahead.peek(kw::Struct) {
213        parse_detached_struct(cx, attrs)
214    } else if lookahead.peek(kw::Enum) {
215        parse_detached_enum(cx, attrs)
216    } else if lookahead.peek(kw::Impl) {
217        parse_detached_impl(cx, attrs)
218    } else if lookahead.peek(kw::Trait) {
219        parse_detached_trait(cx, attrs)
220    } else if lookahead.peek(kw::Static) {
221        parse_detached_static(cx, attrs)
222    } else {
223        Err(lookahead.into_error())
224    }
225}
226
227///```text
228/// ⟨field⟩ ::= ⟨ident⟩ : ⟨type⟩
229/// ```
230fn parse_detached_field(cx: &mut ParseCtxt) -> ParseResult<(Ident, Ty)> {
231    let ident = parse_ident(cx)?;
232    cx.expect(token::Colon)?;
233    let ty = parse_type(cx)?;
234    Ok((ident, ty))
235}
236
237///```text
238/// ⟨enum⟩ := enum Ident ⟨refine_info⟩ { ⟨variant⟩* }
239/// ```
240fn parse_detached_enum(cx: &mut ParseCtxt, mut attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
241    cx.expect(kw::Enum)?;
242    let path = parse_expr_path(cx)?;
243    let generics = Some(parse_opt_generics(cx)?);
244    let refined_by = attrs.refined_by();
245    let invariants = attrs.invariant().into_iter().collect();
246    let variants = braces(cx, Comma, |cx| parse_variant(cx, true))?
247        .into_iter()
248        .map(Some)
249        .collect();
250    let enum_def = EnumDef { generics, refined_by, variants, invariants, reflected: false };
251    Ok(DetachedItem {
252        attrs: attrs.normal,
253        path,
254        kind: DetachedItemKind::Enum(enum_def),
255        node_id: cx.next_node_id(),
256    })
257}
258
259fn parse_detached_struct(cx: &mut ParseCtxt, mut attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
260    cx.expect(kw::Struct)?;
261    let path = parse_expr_path(cx)?;
262    let generics = Some(parse_opt_generics(cx)?);
263    let refined_by = attrs.refined_by();
264    let opaque = attrs.is_opaque();
265    let invariants = attrs.invariant().into_iter().collect();
266    let fields = if cx.peek(token::OpenBrace) {
267        braces(cx, Comma, parse_detached_field)?
268            .into_iter()
269            .map(|(_, ty)| Some(ty))
270            .collect()
271    } else if cx.peek(token::OpenParen) {
272        parens(cx, Comma, parse_type)?
273            .into_iter()
274            .map(Some)
275            .collect()
276    } else {
277        cx.expect(token::Semi)?;
278        vec![]
279    };
280    let struct_def = StructDef { generics, opaque, refined_by, invariants, fields };
281    Ok(DetachedItem {
282        attrs: attrs.normal,
283        path,
284        kind: DetachedItemKind::Struct(struct_def),
285        node_id: cx.next_node_id(),
286    })
287}
288
289fn ident_path(cx: &mut ParseCtxt, ident: Ident) -> ExprPath {
290    let span = ident.span;
291    let segments = vec![ExprPathSegment { ident, node_id: cx.next_node_id() }];
292    ExprPath { segments, span, node_id: cx.next_node_id() }
293}
294
295fn parse_detached_fn_sig(
296    cx: &mut ParseCtxt,
297    mut attrs: ParsedAttrs,
298) -> ParseResult<DetachedItem<FnSig>> {
299    let mut fn_sig = parse_fn_sig(cx, token::Semi)?;
300    fn_sig.no_panic = attrs.no_panic_if();
301    let span = fn_sig.span;
302    let ident = fn_sig
303        .ident
304        .ok_or(ParseError { kind: crate::ParseErrorKind::InvalidDetachedSpec, span })?;
305    let path = ident_path(cx, ident);
306    Ok(DetachedItem { attrs: attrs.normal, path, kind: fn_sig, node_id: cx.next_node_id() })
307}
308
309///```text
310/// ⟨static-spec⟩ ::= static ⟨ident⟩ : ⟨type⟩ ;
311/// ```
312fn parse_detached_static(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
313    cx.expect(kw::Static)?;
314    let path = parse_expr_path(cx)?;
315    cx.expect(token::Colon)?;
316    let ty = parse_type(cx)?;
317    cx.expect(token::Semi)?;
318    Ok(DetachedItem {
319        attrs: attrs.normal,
320        path,
321        kind: DetachedItemKind::Static(StaticInfo { ty }),
322        node_id: cx.next_node_id(),
323    })
324}
325
326///```text
327/// ⟨mod⟩ ::= mod ⟨ident⟩ { ⟨specs⟩ }
328/// ```
329fn parse_detached_mod(cx: &mut ParseCtxt) -> ParseResult<DetachedItem> {
330    cx.expect(kw::Mod)?;
331    let path = parse_expr_path(cx)?;
332    cx.expect(TokenKind::open_delim(Brace))?;
333    let items = until(cx, TokenKind::close_delim(Brace), parse_detached_item)?;
334    cx.expect(TokenKind::close_delim(Brace))?;
335    Ok(DetachedItem {
336        attrs: vec![],
337        path,
338        kind: DetachedItemKind::Mod(DetachedSpecs { items }),
339        node_id: cx.next_node_id(),
340    })
341}
342
343///```text
344/// ⟨trait-spec⟩ ::= trait Ident { ⟨fn-spec⟩* }
345/// ```
346fn parse_detached_trait(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
347    cx.expect(kw::Trait)?;
348    let path = parse_expr_path(cx)?;
349    let _generics = parse_opt_generics(cx)?;
350    cx.expect(TokenKind::open_delim(Brace))?;
351
352    let mut items = vec![];
353    let mut refts = vec![];
354    while !cx.peek(TokenKind::close_delim(Brace)) {
355        let assoc_item_attrs = parse_attrs(cx)?;
356        if assoc_item_attrs.is_reft() {
357            refts.push(parse_trait_assoc_reft(cx)?);
358        } else {
359            items.push(parse_detached_fn_sig(cx, assoc_item_attrs)?);
360        }
361    }
362    cx.expect(TokenKind::close_delim(Brace))?;
363    Ok(DetachedItem {
364        attrs: attrs.normal,
365        path,
366        kind: DetachedItemKind::Trait(DetachedTrait { items, refts }),
367        node_id: cx.next_node_id(),
368    })
369}
370
371///```text
372/// ⟨impl-spec⟩ ::= impl Ident (for Ident)? { ⟨#[assoc] impl_assoc_reft⟩* ⟨fn-spec⟩* }
373/// ```
374fn parse_detached_impl(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
375    let lo = cx.lo();
376    cx.expect(kw::Impl)?;
377    let hi = cx.hi();
378    let span = cx.mk_span(lo, hi);
379    let outer_path = parse_expr_path(cx)?;
380    let _generics = parse_opt_generics(cx)?;
381    let inner_path = if cx.advance_if(kw::For) {
382        let path = parse_expr_path(cx)?;
383        let _generics = parse_opt_generics(cx)?;
384        Some(path)
385    } else {
386        None
387    };
388    cx.expect(TokenKind::open_delim(Brace))?;
389
390    let mut items = vec![];
391    let mut refts = vec![];
392    while !cx.peek(TokenKind::close_delim(Brace)) {
393        // if inner_path.is_none, we are parsing an inherent impl with no associated-refts
394        let assoc_item_attrs = parse_attrs(cx)?;
395        if assoc_item_attrs.is_reft() && inner_path.is_some() {
396            refts.push(parse_impl_assoc_reft(cx)?);
397        } else {
398            items.push(parse_detached_fn_sig(cx, assoc_item_attrs)?);
399        }
400    }
401    cx.expect(TokenKind::close_delim(Brace))?;
402    if let Some(path) = inner_path {
403        Ok(DetachedItem {
404            attrs: attrs.normal,
405            path,
406            kind: DetachedItemKind::TraitImpl(DetachedTraitImpl {
407                trait_: outer_path,
408                items,
409                refts,
410                span,
411            }),
412            node_id: cx.next_node_id(),
413        })
414    } else {
415        Ok(DetachedItem {
416            attrs: attrs.normal,
417            path: outer_path,
418            kind: DetachedItemKind::InherentImpl(DetachedInherentImpl { items, span }),
419            node_id: cx.next_node_id(),
420        })
421    }
422}
423
424fn parse_attr(cx: &mut ParseCtxt, attrs: &mut ParsedAttrs) -> ParseResult {
425    cx.expect(token::Pound)?;
426    cx.expect(token::OpenBracket)?;
427    let mut lookahead = cx.lookahead1();
428    if lookahead.advance_if(kw::Trusted) {
429        if cx.advance_if(token::OpenParen) {
430            parse_reason(cx)?;
431            cx.expect(token::CloseParen)?;
432        }
433        attrs.normal.push(Attr::Trusted(Trusted::Yes));
434    } else if lookahead.advance_if(sym::hide) {
435        attrs.syntax.push(SyntaxAttr::Hide);
436    } else if lookahead.advance_if(kw::Opaque) {
437        attrs.syntax.push(SyntaxAttr::Opaque);
438    } else if lookahead.advance_if(kw::Reft) {
439        attrs.syntax.push(SyntaxAttr::Reft);
440    } else if lookahead.advance_if(kw::RefinedBy) {
441        attrs
442            .syntax
443            .push(SyntaxAttr::RefinedBy(delimited(cx, Parenthesis, parse_refined_by)?));
444    } else if lookahead.advance_if(kw::Invariant) {
445        attrs
446            .syntax
447            .push(SyntaxAttr::Invariant(delimited(cx, Parenthesis, |cx| parse_expr(cx, true))?));
448    } else if lookahead.advance_if(sym::no_panic_if) {
449        attrs
450            .syntax
451            .push(SyntaxAttr::NoPanicIf(parse_expr(cx, true)?));
452    } else {
453        return Err(lookahead.into_error());
454    };
455    cx.expect(token::CloseBracket)
456}
457
458fn parse_attrs(cx: &mut ParseCtxt) -> ParseResult<ParsedAttrs> {
459    let mut attrs = ParsedAttrs::default();
460    repeat_while(cx, token::Pound, |cx| parse_attr(cx, &mut attrs))?;
461    Ok(attrs)
462}
463
464/// ```text
465/// ⟨func_def⟩ := ⟨ # [ hide ] ⟩?
466///               fn ⟨ident⟩ ⟨ < ⟨ident⟩,* > ⟩?
467///               ( ⟨refine_param⟩,* )
468///               ->
469///               ⟨sort⟩
470/// ```
471fn parse_reft_func(cx: &mut ParseCtxt) -> ParseResult<SpecFunc> {
472    let attrs = parse_attrs(cx)?;
473    let hide = attrs.is_hide();
474    cx.expect(kw::Fn)?;
475    let name = parse_ident(cx)?;
476    let sort_vars = opt_angle(cx, Comma, parse_ident)?;
477    let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
478    cx.expect(token::RArrow)?;
479    let output = parse_sort(cx)?;
480    let body = if cx.peek(token::OpenBrace) {
481        Some(parse_block(cx)?)
482    } else {
483        cx.expect(token::Semi)?;
484        None
485    };
486    Ok(SpecFunc { name, sort_vars, params, output, body, hide })
487}
488
489/// ```text
490/// ⟨qualifier_kind⟩ :=  local
491///                   |  invariant
492/// ```
493fn parse_qualifier_kind(cx: &mut ParseCtxt) -> ParseResult<QualifierKind> {
494    let mut lookahead = cx.lookahead1();
495    if lookahead.advance_if(kw::Local) {
496        Ok(QualifierKind::Local)
497    } else if lookahead.advance_if(kw::Invariant) {
498        Ok(QualifierKind::Hint)
499    } else {
500        Ok(QualifierKind::Global)
501    }
502}
503
504/// ```text
505/// ⟨qualifier⟩ :=  ⟨ qualifier_kind ⟩?
506///                 qualifier ⟨ident⟩ ( ⟨qualifier_param⟩,* )
507///                 ⟨block⟩
508/// ```
509fn parse_qualifier(cx: &mut ParseCtxt) -> ParseResult<Qualifier> {
510    let lo = cx.lo();
511    let kind = parse_qualifier_kind(cx)?;
512    cx.expect(kw::Qualifier)?;
513    let mut name = parse_ident(cx)?;
514    let (mut params, mut wildcards): (RefineParams, Vec<bool>) =
515        parens(cx, Comma, parse_qualifier_param)?
516            .into_iter()
517            .unzip();
518    let expr = parse_block(cx)?;
519    let hi = cx.hi();
520
521    if let QualifierKind::Hint = kind {
522        // Append the body's free variables that weren't given an explicit sort, keeping the
523        // order in which they appear in the body.
524        let explicit: UnordSet<_> = params.iter().map(|param| param.ident).collect();
525        params.extend(
526            expr.free_vars()
527                .into_iter()
528                .filter(|ident| !explicit.contains(ident))
529                .map(|ident| {
530                    RefineParam {
531                        ident,
532                        sort: Sort::Infer,
533                        mode: None,
534                        span: ident.span,
535                        node_id: cx.next_node_id(),
536                    }
537                }),
538        );
539        // Params synthesized from the body's free variables are bound to values in the enclosing
540        // function, so they are never wildcards.
541        wildcards.resize(params.len(), false);
542
543        // Uniquify the name so hints don't collide with each other (qualifier names are
544        // crate-global). The span alone is not enough: every expansion of a macro like
545        // `qualifier!` transcribes the same `name` token, so all of them share a span. The
546        // node id is a session-global counter, so it distinguishes them.
547        let span = name.span;
548        let str = format!(
549            "{}_{}_{}_{}",
550            name.name.to_ident_string(),
551            span.lo().0,
552            span.hi().0,
553            cx.next_node_id().as_usize()
554        );
555        name = Ident { name: Symbol::intern(&str), ..name };
556    }
557
558    debug_assert_eq!(params.len(), wildcards.len());
559    Ok(Qualifier { name, params, wildcards, expr, span: cx.mk_span(lo, hi), kind })
560}
561
562/// ```text
563/// ⟨sort_decl⟩ := opaque sort ⟨ident⟩ ;
564/// ```
565fn parse_sort_decl(cx: &mut ParseCtxt) -> ParseResult<SortDecl> {
566    cx.expect(kw::Opaque)?;
567    cx.expect(kw::Sort)?;
568    let name = parse_ident(cx)?;
569    let sort_vars = opt_angle(cx, Comma, parse_ident)?;
570    cx.expect(token::Semi)?;
571    Ok(SortDecl { name, sort_vars })
572}
573
574/// `⟨bin_op⟩ := ⟨ a binary operator ⟩
575fn parse_binop(cx: &mut ParseCtxt) -> ParseResult<BinOp> {
576    let (op, ntokens) = cx
577        .peek_binop()
578        .ok_or_else(|| cx.unexpected_token(vec![Expected::Str("binary operator")]))?;
579    cx.advance_by(ntokens);
580    Ok(op)
581}
582
583/// ```text
584/// ⟨primop_prop⟩ := property ⟨ident⟩ [ ⟨bin_op⟩ ] ( ⟨refine_param⟩,* ) ⟨block⟩
585/// ```
586fn parse_primop_property(cx: &mut ParseCtxt) -> ParseResult<PrimOpProp> {
587    let lo = cx.lo();
588    cx.expect(kw::Property)?;
589
590    // Parse the name
591    let name = parse_ident(cx)?;
592
593    // Parse the operator
594    cx.expect(token::OpenBracket)?;
595    let op = parse_binop(cx)?;
596    cx.expect(token::CloseBracket)?;
597
598    // Parse the args
599    let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::No))?;
600
601    let body = parse_block(cx)?;
602    let hi = cx.hi();
603
604    Ok(PrimOpProp { name, op, params, body, span: cx.mk_span(lo, hi) })
605}
606
607/// ```text
608/// ⟨use_item⟩ := use ⟨use_tree⟩ ;
609/// ```
610fn parse_use_item(cx: &mut ParseCtxt) -> ParseResult<UseTree> {
611    cx.expect(kw::Use)?;
612    let tree = parse_use_tree(cx)?;
613    cx.expect(token::Semi)?;
614    Ok(tree)
615}
616
617/// ```text
618/// ⟨use_tree⟩ := ⟨ident⟩ ( :: ⟨ident⟩ )* ( :: { ⟨use_tree⟩,* } )?
619/// ```
620fn parse_use_tree(cx: &mut ParseCtxt) -> ParseResult<UseTree> {
621    let lo = cx.lo();
622    let mut segments = vec![parse_expr_path_segment(cx)?];
623    let mut hi = cx.hi();
624    let kind = loop {
625        if !cx.advance_if(token::PathSep) {
626            break UseTreeKind::Simple;
627        }
628        if cx.advance_if(token::OpenBrace) {
629            let items = punctuated_until(cx, token::Comma, token::CloseBrace, parse_use_tree)?;
630            cx.expect(token::CloseBrace)?;
631            break UseTreeKind::Nested(items);
632        }
633        segments.push(parse_expr_path_segment(cx)?);
634        hi = cx.hi();
635    };
636    let prefix = ExprPath { segments, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) };
637    Ok(UseTree { prefix, kind })
638}
639
640pub(crate) fn parse_trait_assoc_refts(cx: &mut ParseCtxt) -> ParseResult<Vec<TraitAssocReft>> {
641    until(cx, token::Eof, parse_trait_assoc_reft)
642}
643
644/// ```text
645/// ⟨trait_assoc_reft⟩ := fn ⟨ident⟩ ( ⟨refine_param⟩,* ) -> ⟨base_sort⟩ ;?
646///                     | fn ⟨ident⟩ ( ⟨refine_param⟩,* ) -> ⟨base_sort⟩ ⟨block⟩
647///                     | final fn ⟨ident⟩ ( ⟨refine_param⟩,* ) -> ⟨base_sort⟩ ⟨block⟩
648/// ```
649fn parse_trait_assoc_reft(cx: &mut ParseCtxt) -> ParseResult<TraitAssocReft> {
650    let lo = cx.lo();
651    let final_ = cx.advance_if(kw::Final);
652    cx.expect(kw::Fn)?;
653    let name = parse_ident(cx)?;
654    let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
655    cx.expect(token::RArrow)?;
656    let output = parse_base_sort(cx)?;
657    let body = if cx.peek(token::OpenBrace) {
658        Some(parse_block(cx)?)
659    } else {
660        cx.advance_if(token::Semi);
661        None
662    };
663    let hi = cx.hi();
664    Ok(TraitAssocReft { name, params, output, body, span: cx.mk_span(lo, hi), final_ })
665}
666
667pub(crate) fn parse_impl_assoc_refts(cx: &mut ParseCtxt) -> ParseResult<Vec<ImplAssocReft>> {
668    until(cx, token::Eof, parse_impl_assoc_reft)
669}
670
671/// ```text
672/// ⟨impl_assoc_reft⟩ := fn ⟨ident⟩ ( ⟨refine_param⟩,* ) -> ⟨base_sort⟩ ⟨block⟩
673/// ```
674fn parse_impl_assoc_reft(cx: &mut ParseCtxt) -> ParseResult<ImplAssocReft> {
675    let lo = cx.lo();
676    cx.expect(kw::Fn)?;
677    let name = parse_ident(cx)?;
678    let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
679    cx.expect(token::RArrow)?;
680    let output = parse_base_sort(cx)?;
681    let body = parse_block(cx)?;
682    let hi = cx.hi();
683    Ok(ImplAssocReft { name, params, output, body, span: cx.mk_span(lo, hi) })
684}
685
686/// ```text
687/// ⟨refined_by⟩ := ⟨refine_param⟩,*
688/// ```
689pub(crate) fn parse_refined_by(cx: &mut ParseCtxt) -> ParseResult<RefineParams> {
690    punctuated_until(cx, Comma, token::Eof, |cx| parse_refine_param(cx, RequireSort::Yes))
691}
692
693/// ```text
694/// ⟨variant⟩ := ⟨fields⟩ -> ⟨variant_ret⟩
695///            | ⟨fields⟩
696///            | ⟨variant_ret⟩
697/// ```
698pub(crate) fn parse_variant(cx: &mut ParseCtxt, ret_arrow: bool) -> ParseResult<VariantDef> {
699    let lo = cx.lo();
700    let mut fields = vec![];
701    let mut ret = None;
702    let ident = if ret_arrow || cx.peek2(NonReserved, token::OpenParen) {
703        Some(parse_ident(cx)?)
704    } else {
705        None
706    };
707    if cx.peek(token::OpenParen) || cx.peek(token::OpenBrace) {
708        fields = parse_fields(cx)?;
709        if cx.advance_if(token::RArrow) {
710            ret = Some(parse_variant_ret(cx)?);
711        }
712    } else {
713        if ret_arrow {
714            cx.expect(token::RArrow)?;
715        }
716        ret = Some(parse_variant_ret(cx)?);
717    };
718    let hi = cx.hi();
719    Ok(VariantDef { ident, fields, ret, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
720}
721
722/// ```text
723/// ⟨fields⟩ := ( ⟨ty⟩,* ) | { ⟨ty⟩,* }
724/// ```
725fn parse_fields(cx: &mut ParseCtxt) -> ParseResult<Vec<Ty>> {
726    let mut lookahead = cx.lookahead1();
727    if lookahead.peek(token::OpenParen) {
728        parens(cx, Comma, parse_type)
729    } else if lookahead.peek(token::OpenBrace) {
730        braces(cx, Comma, parse_type)
731    } else {
732        Err(lookahead.into_error())
733    }
734}
735
736/// ```text
737/// ⟨variant_ret⟩ := ⟨path⟩ ⟨ [ ⟨refine_arg⟩,? ] ⟩?
738/// ```
739fn parse_variant_ret(cx: &mut ParseCtxt) -> ParseResult<VariantRet> {
740    let path = parse_path(cx)?;
741    let indices = if cx.peek(token::OpenBracket) {
742        parse_indices(cx)?
743    } else {
744        let hi = cx.hi();
745        Indices { indices: vec![], span: cx.mk_span(hi, hi) }
746    };
747    Ok(VariantRet { path, indices })
748}
749
750pub(crate) fn parse_type_alias(cx: &mut ParseCtxt) -> ParseResult<TyAlias> {
751    let lo = cx.lo();
752    cx.expect(kw::Type)?;
753    let ident = parse_ident(cx)?;
754    let generics = parse_opt_generics(cx)?;
755    let params = if cx.peek(token::OpenParen) {
756        parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?
757    } else {
758        vec![]
759    };
760    let index = if cx.peek(token::OpenBracket) {
761        Some(delimited(cx, Bracket, |cx| parse_refine_param(cx, RequireSort::Yes))?)
762    } else {
763        None
764    };
765    cx.expect(token::Eq)?;
766    let ty = parse_type(cx)?;
767    let hi = cx.hi();
768    Ok(TyAlias {
769        ident,
770        generics,
771        params,
772        index,
773        ty,
774        node_id: cx.next_node_id(),
775        span: cx.mk_span(lo, hi),
776    })
777}
778
779fn parse_opt_generics(cx: &mut ParseCtxt) -> ParseResult<Generics> {
780    if !cx.peek(LAngle) {
781        let hi = cx.hi();
782        return Ok(Generics { params: vec![], predicates: None, span: cx.mk_span(hi, hi) });
783    }
784    let lo = cx.lo();
785    let params = angle(cx, Comma, parse_generic_param)?;
786    let hi = cx.hi();
787    Ok(Generics { params, predicates: None, span: cx.mk_span(lo, hi) })
788}
789
790fn parse_generic_param(cx: &mut ParseCtxt) -> ParseResult<GenericParam> {
791    let name = parse_ident(cx)?;
792    Ok(GenericParam { name, node_id: cx.next_node_id() })
793}
794
795fn invalid_ident_err(ident: &Ident) -> ParseError {
796    ParseError { kind: crate::ParseErrorKind::InvalidBinding, span: ident.span }
797}
798
799fn mut_as_strg(inputs: Vec<FnInput>, ensures: &[Ensures]) -> ParseResult<Vec<FnInput>> {
800    // 1. Gather ensures
801    let locs = ensures
802        .iter()
803        .filter_map(|ens| if let Ensures::Type(ident, _, _) = ens { Some(ident) } else { None })
804        .collect::<HashSet<_>>();
805    // 2. Walk over inputs and transform references mentioned in ensures
806    let mut res = vec![];
807    for input in inputs {
808        if let FnInput::Ty(Some(ident), _, _) = &input
809            && locs.contains(&ident)
810        {
811            // a known location: better be a mut or else, error!
812            let FnInput::Ty(Some(ident), ty, id) = input else {
813                return Err(invalid_ident_err(ident));
814            };
815            let TyKind::Ref(Mutability::Mut, inner_ty) = ty.kind else {
816                return Err(invalid_ident_err(&ident));
817            };
818            res.push(FnInput::StrgRef(ident, *inner_ty, id));
819        } else {
820            // not a known location, leave unchanged
821            res.push(input);
822        }
823    }
824    Ok(res)
825}
826
827/// ```text
828/// ⟨fn_sig⟩ := ⟨asyncness⟩ fn ⟨ident⟩?
829///             ⟨ [ ⟨refine_param⟩,* ] ⟩?
830///             ( ⟨fn_inputs⟩,* )
831///             ⟨-> ⟨ty⟩⟩?
832///             ⟨requires⟩ ⟨ensures⟩ ⟨where⟩
833/// ```
834pub(crate) fn parse_fn_sig<T: PeekExpected>(cx: &mut ParseCtxt, end: T) -> ParseResult<FnSig> {
835    let lo = cx.lo();
836    let asyncness = parse_asyncness(cx);
837    cx.expect(kw::Fn)?;
838    let ident = if cx.peek(NonReserved) { Some(parse_ident(cx)?) } else { None };
839    let mut generics = parse_opt_generics(cx)?;
840    let params = if cx.peek(token::OpenBracket) {
841        brackets(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?
842    } else {
843        vec![]
844    };
845    let inputs = parens(cx, Comma, parse_fn_input)?;
846    let returns = parse_fn_ret(cx)?;
847    let requires = parse_opt_requires(cx)?;
848    let ensures = parse_opt_ensures(cx)?;
849    let inputs = mut_as_strg(inputs, &ensures)?;
850    generics.predicates = parse_opt_where(cx)?;
851    cx.expect(end)?;
852    let hi = cx.hi();
853    Ok(FnSig {
854        asyncness,
855        generics,
856        params,
857        ident,
858        inputs,
859        requires,
860        output: FnOutput { returns, ensures, node_id: cx.next_node_id() },
861        node_id: cx.next_node_id(),
862        span: cx.mk_span(lo, hi),
863        no_panic: None, // We attach the `no_panic` expr later
864    })
865}
866
867/// ```text
868/// ⟨requires⟩ := ⟨ requires ⟨requires_clause⟩,* ⟩?
869/// ```
870fn parse_opt_requires(cx: &mut ParseCtxt) -> ParseResult<Vec<Requires>> {
871    if !cx.advance_if(kw::Requires) {
872        return Ok(vec![]);
873    }
874    punctuated_until(
875        cx,
876        Comma,
877        |t: TokenKind| t.is_keyword(kw::Ensures) || t.is_keyword(kw::Where) || t.is_eof(),
878        parse_requires_clause,
879    )
880}
881
882/// ```text
883/// ⟨requires_clause⟩ := ⟨ forall ⟨refine_param⟩,+ . ⟩? ⟨expr⟩
884/// ```
885fn parse_requires_clause(cx: &mut ParseCtxt) -> ParseResult<Requires> {
886    let mut params = vec![];
887    if cx.advance_if(kw::Forall) {
888        params = sep1(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
889        cx.expect(token::Dot)?;
890    }
891    let pred = parse_expr(cx, true)?;
892    Ok(Requires { params, pred })
893}
894
895/// ```text
896/// ⟨ensures⟩ := ⟨ensures ⟨ensures_clause⟩,*⟩?
897/// ```
898fn parse_opt_ensures(cx: &mut ParseCtxt) -> ParseResult<Vec<Ensures>> {
899    if !cx.advance_if(kw::Ensures) {
900        return Ok(vec![]);
901    }
902    punctuated_until(
903        cx,
904        Comma,
905        |t: TokenKind| t.is_keyword(kw::Where) || t.is_eof(),
906        parse_ensures_clause,
907    )
908}
909
910/// ```text
911/// ⟨ensures_clause⟩ :=  ⟨ident⟩ : ⟨ty⟩
912///                   |  ⟨expr⟩
913/// ```
914fn parse_ensures_clause(cx: &mut ParseCtxt) -> ParseResult<Ensures> {
915    if cx.peek2(NonReserved, token::Colon) {
916        // ⟨ident⟩ : ⟨ty⟩
917        let ident = parse_ident(cx)?;
918        cx.expect(token::Colon)?;
919        let ty = parse_type(cx)?;
920        Ok(Ensures::Type(ident, ty, cx.next_node_id()))
921    } else {
922        // ⟨expr⟩
923        Ok(Ensures::Pred(parse_expr(cx, true)?))
924    }
925}
926
927fn parse_opt_where(cx: &mut ParseCtxt) -> ParseResult<Option<Vec<WhereBoundPredicate>>> {
928    if !cx.advance_if(kw::Where) {
929        return Ok(None);
930    }
931    Ok(Some(punctuated_until(cx, Comma, token::Eof, parse_where_bound)?))
932}
933
934fn parse_where_bound(cx: &mut ParseCtxt) -> ParseResult<WhereBoundPredicate> {
935    let lo = cx.lo();
936    let bounded_ty = parse_type(cx)?;
937    cx.expect(token::Colon)?;
938    let bounds = parse_generic_bounds(cx)?;
939    let hi = cx.hi();
940    Ok(WhereBoundPredicate { span: cx.mk_span(lo, hi), bounded_ty, bounds })
941}
942
943/// ```text
944/// ⟨fn_ret⟩ := ⟨ -> ⟨ty⟩ ⟩?
945/// ```
946fn parse_fn_ret(cx: &mut ParseCtxt) -> ParseResult<FnRetTy> {
947    if cx.advance_if(token::RArrow) {
948        Ok(FnRetTy::Ty(Box::new(parse_type(cx)?)))
949    } else {
950        let hi = cx.hi();
951        Ok(FnRetTy::Default(cx.mk_span(hi, hi)))
952    }
953}
954
955/// ```text
956/// ⟨fn_input⟩ := ⟨ident⟩ : &strg ⟨ty⟩
957///             | ⟨ident⟩ : ⟨path⟩ { ⟨expr⟩ }
958///             | ⟨ident⟩ : ⟨ty⟩
959///             | ⟨ty⟩
960/// ```
961fn parse_fn_input(cx: &mut ParseCtxt) -> ParseResult<FnInput> {
962    if cx.peek2(NonReserved, token::Colon) {
963        let bind = parse_ident(cx)?;
964        cx.expect(token::Colon)?;
965        if cx.advance_if2(token::And, kw::Strg) {
966            // ⟨ident⟩ : &strg ⟨ty⟩
967            Ok(FnInput::StrgRef(bind, parse_type(cx)?, cx.next_node_id()))
968        } else if cx.peek(NonReserved) {
969            let path = parse_path(cx)?;
970            if cx.peek3(token::OpenBrace, NonReserved, token::Colon) {
971                // ⟨ident⟩ : ⟨path⟩ { ⟨ident⟩ : ⟨expr⟩ }
972                let bty = path_to_bty(path);
973                let ty = parse_bty_exists(cx, bty)?;
974                Ok(FnInput::Ty(Some(bind), ty, cx.next_node_id()))
975            } else if cx.peek(token::OpenBrace) {
976                // ⟨ident⟩ : ⟨path⟩ { ⟨expr⟩ }
977                let pred = delimited(cx, Brace, |cx| parse_expr(cx, true))?;
978                Ok(FnInput::Constr(bind, path, pred, cx.next_node_id()))
979            } else {
980                // ⟨ident⟩ : ⟨ty⟩
981                let bty = path_to_bty(path);
982                let ty = parse_bty_rhs(cx, bty)?;
983                Ok(FnInput::Ty(Some(bind), ty, cx.next_node_id()))
984            }
985        } else {
986            // ⟨ident⟩ : ⟨ty⟩
987            Ok(FnInput::Ty(Some(bind), parse_type(cx)?, cx.next_node_id()))
988        }
989    } else {
990        // ⟨ty⟩
991        Ok(FnInput::Ty(None, parse_type(cx)?, cx.next_node_id()))
992    }
993}
994
995/// ```text
996/// ⟨asyncness⟩ := async?
997/// ```
998fn parse_asyncness(cx: &mut ParseCtxt) -> Async {
999    let lo = cx.lo();
1000    if cx.advance_if(kw::Async) {
1001        Async::Yes { node_id: cx.next_node_id(), span: cx.mk_span(lo, cx.hi()) }
1002    } else {
1003        Async::No
1004    }
1005}
1006
1007enum Reft {
1008    Exi(Ident, Expr),
1009    Idx(Indices),
1010    None,
1011}
1012
1013fn parse_reft(cx: &mut ParseCtxt) -> ParseResult<Reft> {
1014    if cx.peek(token::OpenBrace) {
1015        let (bind, pred) = delimited(cx, Brace, |cx| {
1016            let bind = parse_ident(cx)?;
1017            cx.expect(token::Colon)?;
1018            let pred = parse_block_expr(cx)?;
1019            Ok((bind, pred))
1020        })?;
1021        Ok(Reft::Exi(bind, pred))
1022    } else if cx.peek(token::OpenBracket) {
1023        let indices = parse_indices(cx)?;
1024        Ok(Reft::Idx(indices))
1025    } else {
1026        Ok(Reft::None)
1027    }
1028}
1029
1030/// ```text
1031/// ⟨ty⟩ := _
1032///       | { ⟨ident⟩ ⟨,⟨ident⟩⟩* . ⟨ty⟩ | ⟨block_expr⟩ }
1033///       | ( ⟨ty⟩,* )
1034///       | { ⟨ty⟩ | ⟨block_expr⟩ }
1035///       | { ⟨refine_param⟩ ⟨,⟨refine_param⟩⟩* . ⟨ty⟩ | ⟨block_expr⟩ }
1036///       | & mut? ⟨ty⟩
1037///       | * const ⟨ { ⟨ident⟩ : ⟨expr⟩ } ⟩? ⟨ty⟩
1038///       | * mut ⟨ { ⟨ident⟩ : ⟨expr⟩ } ⟩? ⟨ty⟩
1039///       | [ ⟨ty⟩ ; ⟨const_arg⟩ ]
1040///       | impl ⟨path⟩
1041///       | ⟨bty⟩
1042///       | ⟨bty⟩ [ ⟨refine_arg⟩,* ]
1043///       | ⟨bty⟩ { ⟨ident⟩ : ⟨block_expr⟩ }
1044///
1045/// ⟨bty⟩ := ⟨path⟩ | ⟨qpath⟩ | [ ⟨ty⟩ ]
1046/// ```
1047pub(crate) fn parse_type(cx: &mut ParseCtxt) -> ParseResult<Ty> {
1048    let lo = cx.lo();
1049    let mut lookahead = cx.lookahead1();
1050    let kind = if lookahead.advance_if(kw::Underscore) {
1051        TyKind::Hole
1052    } else if lookahead.advance_if(token::OpenParen) {
1053        // ( ⟨ty⟩,* )
1054        let (mut tys, trailing) =
1055            punctuated_with_trailing(cx, Comma, token::CloseParen, parse_type)?;
1056        cx.expect(token::CloseParen)?;
1057        if tys.len() == 1 && !trailing {
1058            return Ok(tys.remove(0));
1059        } else {
1060            TyKind::Tuple(tys)
1061        }
1062    } else if lookahead.peek(token::OpenBrace) {
1063        delimited(cx, Brace, |cx| {
1064            if cx.peek2(NonReserved, AnyOf([token::Comma, token::Dot, token::Colon])) {
1065                // { ⟨refine_param⟩ ⟨,⟨refine_param⟩⟩* . ⟨ty⟩ | ⟨block_expr⟩ }
1066                parse_general_exists(cx)
1067            } else {
1068                // { ⟨ty⟩ | ⟨block_expr⟩ }
1069                let ty = parse_type(cx)?;
1070                cx.expect(token::Or)?;
1071                let pred = parse_block_expr(cx)?;
1072                Ok(TyKind::Constr(pred, Box::new(ty)))
1073            }
1074        })?
1075    } else if lookahead.advance_if(token::And) {
1076        //  & mut? ⟨ty⟩
1077        let mutbl = if cx.advance_if(kw::Mut) { Mutability::Mut } else { Mutability::Not };
1078        TyKind::Ref(mutbl, Box::new(parse_type(cx)?))
1079    } else if lookahead.advance_if(token::Star) {
1080        //  * const ⟨ { ⟨ident⟩ : ⟨expr⟩ } ⟩? ⟨ty⟩ | * mut ⟨ { ⟨ident⟩ : ⟨expr⟩ } ⟩? ⟨ty⟩
1081        let mutbl = if cx.advance_if(kw::Mut) {
1082            Mutability::Mut
1083        } else {
1084            cx.expect(kw::Const)?;
1085            Mutability::Not
1086        };
1087        // Parse optional refinement on the pointer value: {v: pred}
1088        let reft = parse_reft(cx)?;
1089        let inner_ty = parse_type(cx)?;
1090        let bty = BaseTy {
1091            kind: BaseTyKind::Ptr(mutbl, Box::new(inner_ty)),
1092            span: cx.mk_span(lo, cx.hi()),
1093        };
1094        match reft {
1095            Reft::Exi(bind, pred) => TyKind::Exists { bind, bty, pred },
1096            Reft::Idx(indices) => TyKind::Indexed { bty, indices },
1097            Reft::None => TyKind::Base(bty),
1098        }
1099    } else if lookahead.advance_if(token::OpenBracket) {
1100        let ty = parse_type(cx)?;
1101        if cx.advance_if(token::Semi) {
1102            // [ ⟨ty⟩ ; ⟨const_arg⟩ ]
1103            let len = parse_const_arg(cx)?;
1104            cx.expect(token::CloseBracket)?;
1105            TyKind::Array(Box::new(ty), len)
1106        } else {
1107            // [ ⟨ty⟩ ] ...
1108            cx.expect(token::CloseBracket)?;
1109            let span = cx.mk_span(lo, cx.hi());
1110            let kind = BaseTyKind::Slice(Box::new(ty));
1111            return parse_bty_rhs(cx, BaseTy { kind, span });
1112        }
1113    } else if lookahead.advance_if(kw::Impl) {
1114        // impl ⟨bounds⟩
1115        TyKind::ImplTrait(cx.next_node_id(), parse_generic_bounds(cx)?)
1116    } else if lookahead.peek(NonReserved) {
1117        // ⟨path⟩ ...
1118        let path = parse_path(cx)?;
1119        let bty = path_to_bty(path);
1120        return parse_bty_rhs(cx, bty);
1121    } else if lookahead.peek(LAngle) {
1122        // ⟨qpath⟩ ...
1123        let bty = parse_qpath(cx)?;
1124        return parse_bty_rhs(cx, bty);
1125    } else {
1126        return Err(lookahead.into_error());
1127    };
1128    let hi = cx.hi();
1129    Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1130}
1131
1132/// ```text
1133/// ⟨qpath⟩ := < ⟨ty⟩ as ⟨segments⟩> :: ⟨segments⟩
1134/// ```
1135fn parse_qpath(cx: &mut ParseCtxt) -> ParseResult<BaseTy> {
1136    let lo = cx.lo();
1137    cx.expect(LAngle)?;
1138    let qself = parse_type(cx)?;
1139    cx.expect(kw::As)?;
1140    let mut segments = parse_segments(cx)?;
1141    cx.expect(RAngle)?;
1142    cx.expect(token::PathSep)?;
1143    segments.extend(parse_segments(cx)?);
1144    let hi = cx.hi();
1145
1146    let span = cx.mk_span(lo, hi);
1147    let path = Path { segments, refine: vec![], node_id: cx.next_node_id(), span };
1148    let kind = BaseTyKind::Path(Some(Box::new(qself)), path);
1149    Ok(BaseTy { kind, span })
1150}
1151
1152/// ```text
1153/// { ⟨refine_param⟩ ⟨,⟨refine_param⟩⟩* . ⟨ty⟩ | ⟨block_expr⟩ }
1154/// ```
1155fn parse_general_exists(cx: &mut ParseCtxt) -> ParseResult<TyKind> {
1156    let params = sep1(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
1157    cx.expect(token::Dot)?;
1158    let ty = parse_type(cx)?;
1159    let pred = if cx.advance_if(token::Or) { Some(parse_block_expr(cx)?) } else { None };
1160    Ok(TyKind::GeneralExists { params, ty: Box::new(ty), pred })
1161}
1162
1163/// ```text
1164///    ⟨bty⟩ [ ⟨refine_arg⟩,* ]
1165/// |  ⟨bty⟩ { ⟨ident⟩ : ⟨block_expr⟩ }
1166/// |  ⟨bty⟩
1167/// ```
1168fn parse_bty_rhs(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
1169    let lo = bty.span.lo();
1170    if cx.peek(token::OpenBracket) {
1171        // ⟨bty⟩ [ ⟨refine_arg⟩,* ]
1172        let indices = parse_indices(cx)?;
1173        let hi = cx.hi();
1174        let kind = TyKind::Indexed { bty, indices };
1175        Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1176    } else if cx.peek(token::OpenBrace) {
1177        // ⟨bty⟩ { ⟨ident⟩ : ⟨block_expr⟩ }
1178        parse_bty_exists(cx, bty)
1179    } else {
1180        // ⟨bty⟩
1181        let hi = cx.hi();
1182        let kind = TyKind::Base(bty);
1183        Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1184    }
1185}
1186
1187/// ```text
1188/// ⟨bty⟩ { ⟨ident⟩ : ⟨block_expr⟩ }
1189/// ```
1190fn parse_bty_exists(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
1191    let lo = bty.span.lo();
1192    delimited(cx, Brace, |cx| {
1193        let bind = parse_ident(cx)?;
1194        cx.expect(token::Colon)?;
1195        let pred = parse_block_expr(cx)?;
1196        let hi = cx.hi();
1197        let kind = TyKind::Exists { bind, bty, pred };
1198        Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1199    })
1200}
1201
1202fn path_to_bty(path: Path) -> BaseTy {
1203    let span = path.span;
1204    BaseTy { kind: BaseTyKind::Path(None, path), span }
1205}
1206
1207fn parse_indices(cx: &mut ParseCtxt) -> ParseResult<Indices> {
1208    let lo = cx.lo();
1209    let indices = brackets(cx, Comma, parse_refine_arg)?;
1210    let hi = cx.hi();
1211    Ok(Indices { indices, span: cx.mk_span(lo, hi) })
1212}
1213
1214fn parse_fn_bound_input(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1215    let lo = cx.lo();
1216    let tys = parens(cx, Comma, parse_type)?;
1217    let hi = cx.hi();
1218    let kind = TyKind::Tuple(tys);
1219    let span = cx.mk_span(lo, hi);
1220    let in_ty = Ty { kind, node_id: cx.next_node_id(), span };
1221    Ok(GenericArg { kind: GenericArgKind::Type(in_ty), node_id: cx.next_node_id() })
1222}
1223
1224fn parse_fn_bound_output(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1225    let lo = cx.lo();
1226
1227    let ty = if cx.advance_if(token::RArrow) {
1228        parse_type(cx)?
1229    } else {
1230        Ty { kind: TyKind::Tuple(vec![]), node_id: cx.next_node_id(), span: cx.mk_span(lo, lo) }
1231    };
1232    let hi = cx.hi();
1233    let ident = Ident { name: Output, span: cx.mk_span(lo, hi) };
1234    Ok(GenericArg { kind: GenericArgKind::Constraint(ident, ty), node_id: cx.next_node_id() })
1235}
1236
1237fn parse_fn_bound_path(cx: &mut ParseCtxt) -> ParseResult<Path> {
1238    let lo = cx.lo();
1239    let ident = parse_ident(cx)?;
1240    let in_arg = parse_fn_bound_input(cx)?;
1241    let out_arg = parse_fn_bound_output(cx)?;
1242    let args = vec![in_arg, out_arg];
1243    let segment = PathSegment { ident, args, node_id: cx.next_node_id() };
1244    let hi = cx.hi();
1245    Ok(Path {
1246        segments: vec![segment],
1247        refine: vec![],
1248        node_id: cx.next_node_id(),
1249        span: cx.mk_span(lo, hi),
1250    })
1251}
1252
1253fn parse_generic_bounds(cx: &mut ParseCtxt) -> ParseResult<GenericBounds> {
1254    let path = if cx.peek(sym::FnOnce) || cx.peek(sym::FnMut) || cx.peek(sym::Fn) {
1255        parse_fn_bound_path(cx)?
1256    } else {
1257        parse_path(cx)?
1258    };
1259    Ok(vec![TraitRef { path, node_id: cx.next_node_id() }])
1260}
1261
1262fn parse_const_arg(cx: &mut ParseCtxt) -> ParseResult<ConstArg> {
1263    let lo = cx.lo();
1264    let mut lookahead = cx.lookahead1();
1265    let kind = if lookahead.peek(AnyLit) {
1266        let len = parse_int(cx)?;
1267        ConstArgKind::Lit(len)
1268    } else if lookahead.peek(NonReserved) {
1269        ConstArgKind::Path(parse_path(cx)?)
1270    } else if lookahead.advance_if(kw::Underscore) {
1271        ConstArgKind::Infer
1272    } else {
1273        return Err(lookahead.into_error());
1274    };
1275    let hi = cx.hi();
1276    Ok(ConstArg { kind, span: cx.mk_span(lo, hi) })
1277}
1278
1279/// ```text
1280/// ⟨path⟩ := ⟨segments⟩ ⟨ ( ⟨refine_arg⟩,* ) ⟩?
1281/// ```
1282fn parse_path(cx: &mut ParseCtxt) -> ParseResult<Path> {
1283    let lo = cx.lo();
1284    let segments = parse_segments(cx)?;
1285    let refine =
1286        if cx.peek(token::OpenParen) { parens(cx, Comma, parse_refine_arg)? } else { vec![] };
1287    let hi = cx.hi();
1288    Ok(Path { segments, refine, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1289}
1290
1291/// ```text
1292/// ⟨segments⟩ := ⟨segment⟩ ⟨:: ⟨segment⟩ ⟩*
1293/// ```
1294fn parse_segments(cx: &mut ParseCtxt) -> ParseResult<Vec<PathSegment>> {
1295    sep1(cx, token::PathSep, parse_segment)
1296}
1297
1298/// ```text
1299/// ⟨segment⟩ := ⟨ident⟩ ⟨ < ⟨generic_arg⟩,* > ⟩?
1300/// ```
1301fn parse_segment(cx: &mut ParseCtxt) -> ParseResult<PathSegment> {
1302    let ident = parse_ident(cx)?;
1303    let args = opt_angle(cx, Comma, parse_generic_arg)?;
1304    Ok(PathSegment { ident, node_id: cx.next_node_id(), args })
1305}
1306
1307/// ```text
1308/// ⟨generic_arg⟩ := ⟨ty⟩ | ⟨ident⟩ = ⟨ty⟩
1309/// ```
1310fn parse_generic_arg(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1311    let kind = if cx.peek2(NonReserved, token::Eq) {
1312        let ident = parse_ident(cx)?;
1313        cx.expect(token::Eq)?;
1314        let ty = parse_type(cx)?;
1315        GenericArgKind::Constraint(ident, ty)
1316    } else {
1317        GenericArgKind::Type(parse_type(cx)?)
1318    };
1319    Ok(GenericArg { kind, node_id: cx.next_node_id() })
1320}
1321
1322/// ```text
1323/// ⟨refine_arg⟩ :=  @ ⟨ident⟩
1324///               |  # ⟨ident⟩
1325///               |  |⟨⟨refine_parm⟩,*| ⟨expr⟩
1326///               |  ⟨expr⟩
1327/// ```
1328fn parse_refine_arg(cx: &mut ParseCtxt) -> ParseResult<RefineArg> {
1329    let lo = cx.lo();
1330    let arg = if cx.advance_if(token::At) {
1331        // @ ⟨ident⟩
1332        let bind = parse_ident(cx)?;
1333        let hi = cx.hi();
1334        RefineArg::Bind(bind, BindKind::At, cx.mk_span(lo, hi), cx.next_node_id())
1335    } else if cx.peek2(token::Pound, NonReserved) {
1336        // # ⟨ident⟩
1337        cx.expect(token::Pound)?;
1338        let bind = parse_ident(cx)?;
1339        let hi = cx.hi();
1340        RefineArg::Bind(bind, BindKind::Pound, cx.mk_span(lo, hi), cx.next_node_id())
1341    } else if cx.advance_if(Or) {
1342        let params =
1343            punctuated_until(cx, Comma, Or, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
1344        cx.expect(Or)?;
1345        let body = parse_expr(cx, true)?;
1346        let hi = cx.hi();
1347        RefineArg::Abs(params, body, cx.mk_span(lo, hi), cx.next_node_id())
1348    } else {
1349        // ⟨expr⟩
1350        RefineArg::Expr(parse_expr(cx, true)?)
1351    };
1352    Ok(arg)
1353}
1354
1355/// Whether a sort is required in a refinement parameter declaration.
1356enum RequireSort {
1357    /// Definitely require a sort
1358    Yes,
1359    /// Optional sort. Use [`Sort::Infer`] if not present
1360    Maybe,
1361    /// Definitely do not not require a sort. Always use [`Sort::Infer`]
1362    No,
1363}
1364
1365fn parse_sort_if_required(cx: &mut ParseCtxt, require_sort: RequireSort) -> ParseResult<Sort> {
1366    match require_sort {
1367        RequireSort::No => Ok(Sort::Infer),
1368        RequireSort::Maybe => {
1369            if cx.advance_if(token::Colon) {
1370                parse_sort(cx)
1371            } else {
1372                Ok(Sort::Infer)
1373            }
1374        }
1375        RequireSort::Yes => {
1376            cx.expect(token::Colon)?;
1377            parse_sort(cx)
1378        }
1379    }
1380}
1381
1382/// ```text
1383/// ⟨refine_param⟩ := ⟨mode⟩? ⟨ident⟩ ⟨ : ⟨sort⟩ ⟩?    if require_sort is Maybe
1384///                 | ⟨mode⟩? ⟨ident⟩ : ⟨sort⟩         if require_sort is Yes
1385///                 | ⟨mode⟩? ⟨ident⟩                  if require_sort is No
1386/// ```
1387fn parse_refine_param(cx: &mut ParseCtxt, require_sort: RequireSort) -> ParseResult<RefineParam> {
1388    let lo = cx.lo();
1389    let mode = parse_opt_param_mode(cx);
1390    let ident = parse_ident(cx)?;
1391    let sort = parse_sort_if_required(cx, require_sort)?;
1392    let hi = cx.hi();
1393    Ok(RefineParam { mode, ident, sort, span: cx.mk_span(lo, hi), node_id: cx.next_node_id() })
1394}
1395
1396/// ```text
1397/// ⟨qualifier_param⟩ := #? ⟨refine_param⟩
1398/// ```
1399///
1400/// `#a: int` rather than fixpoint's `a#: int` because rustc lexes the enclosing attribute first and
1401/// rejects `a#` as a reserved prefix.
1402fn parse_qualifier_param(cx: &mut ParseCtxt) -> ParseResult<(RefineParam, bool)> {
1403    let is_wildcard = cx.advance_if(token::Pound);
1404    let param = parse_refine_param(cx, RequireSort::Yes)?;
1405    Ok((param, is_wildcard))
1406}
1407
1408/// ```text
1409/// ⟨mode⟩ := ⟨ hrn | hdl ⟩?
1410/// ```
1411fn parse_opt_param_mode(cx: &mut ParseCtxt) -> Option<ParamMode> {
1412    if cx.advance_if(kw::Hrn) {
1413        Some(ParamMode::Horn)
1414    } else if cx.advance_if(kw::Hdl) {
1415        Some(ParamMode::Hindley)
1416    } else {
1417        None
1418    }
1419}
1420
1421pub(crate) fn parse_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1422    parse_binops(cx, Precedence::MIN, allow_struct)
1423}
1424
1425fn parse_binops(cx: &mut ParseCtxt, base: Precedence, allow_struct: bool) -> ParseResult<Expr> {
1426    let mut lhs = unary_expr(cx, allow_struct)?;
1427    loop {
1428        let lo = cx.lo();
1429        let Some((op, ntokens)) = cx.peek_binop() else { break };
1430        let precedence = Precedence::of_binop(&op);
1431        if precedence < base {
1432            break;
1433        }
1434        cx.advance_by(ntokens);
1435        let next = match precedence.associativity() {
1436            Associativity::Right => precedence,
1437            Associativity::Left => precedence.next(),
1438            Associativity::None => {
1439                if let ExprKind::BinaryOp(op, ..) = &lhs.kind
1440                    && Precedence::of_binop(op) == precedence
1441                {
1442                    return Err(cx.cannot_be_chained(lo, cx.hi()));
1443                }
1444                precedence.next()
1445            }
1446        };
1447        let rhs = parse_binops(cx, next, allow_struct)?;
1448        let span = lhs.span.to(rhs.span);
1449        lhs = Expr {
1450            kind: ExprKind::BinaryOp(op, Box::new([lhs, rhs])),
1451            node_id: cx.next_node_id(),
1452            span,
1453        }
1454    }
1455    Ok(lhs)
1456}
1457
1458/// ```text
1459/// ⟨unary_expr⟩ := - ⟨unary_expr⟩ | ! ⟨unary_expr⟩ | ⟨trailer_expr⟩
1460/// ```
1461fn unary_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1462    let lo = cx.lo();
1463    let kind = if cx.advance_if(token::Minus) {
1464        ExprKind::UnaryOp(UnOp::Neg, Box::new(unary_expr(cx, allow_struct)?))
1465    } else if cx.advance_if(token::Bang) {
1466        ExprKind::UnaryOp(UnOp::Not, Box::new(unary_expr(cx, allow_struct)?))
1467    } else {
1468        return parse_trailer_expr(cx, allow_struct);
1469    };
1470    let hi = cx.hi();
1471    Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1472}
1473
1474/// ```text
1475/// ⟨trailer_expr⟩ :=  ⟨trailer_expr⟩ . ⟨ident⟩
1476///                 |  ⟨trailer_expr⟩ . ⟨integer⟩
1477///                 |  ⟨trailer_expr⟩ ( ⟨expr⟩,* )
1478///                 |  ⟨atom⟩
1479/// ```
1480fn parse_trailer_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1481    let lo = cx.lo();
1482    let mut e = parse_atom(cx, allow_struct)?;
1483    loop {
1484        let kind = if cx.advance_if(token::Dot) {
1485            if let Token { kind: token::Literal(lit), lo, hi } = cx.at(0)
1486                && let Lit { kind: LitKind::Integer, symbol: name, suffix: None, .. } = lit
1487            {
1488                // ⟨trailer_expr⟩ . ⟨integer⟩
1489                cx.advance();
1490                ExprKind::Dot(Box::new(e), Ident { name, span: cx.mk_span(lo, hi) })
1491            } else {
1492                // ⟨trailer_expr⟩ . ⟨ident⟩
1493                let field = parse_ident(cx)?;
1494                ExprKind::Dot(Box::new(e), field)
1495            }
1496        } else if cx.peek(token::OpenParen) {
1497            // ⟨trailer_expr⟩ ( ⟨expr⟩,* )
1498            let args = parens(cx, Comma, |cx| parse_expr(cx, true))?;
1499            ExprKind::Call(Box::new(e), args)
1500        } else {
1501            break;
1502        };
1503        let hi = cx.hi();
1504        e = Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) };
1505    }
1506    Ok(e)
1507}
1508
1509/// ```text
1510/// ⟨atom⟩ := ⟨if_expr⟩
1511///         | ⟨lit⟩
1512///         | ( ⟨expr⟩ )
1513///         | ( ⟨expr⟩,* )
1514///         | ⟨epath⟩
1515///         | ⟨bounded_quant⟩
1516///         |  <⟨ty⟩ as ⟨path⟩> :: ⟨ident⟩
1517///         | [binop]
1518///         | ⟨epath⟩ { ⟨constructor_arg⟩,* }    if allow_struct
1519///         | { ⟨constructor_arg⟩,* }            if allow_struct
1520///         | #{ ⟨expr⟩,* }
1521/// ```
1522fn parse_atom(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1523    let lo = cx.lo();
1524    let mut lookahead = cx.lookahead1();
1525    if lookahead.peek(kw::If) {
1526        // ⟨if_expr⟩
1527        parse_if_expr(cx)
1528    } else if lookahead.peek(AnyLit) {
1529        // ⟨lit⟩
1530        parse_lit(cx)
1531    } else if lookahead.advance_if(token::OpenParen) {
1532        // ( ⟨expr⟩ ) | ( ⟨expr⟩,* )
1533        let (mut exprs, trailing) =
1534            punctuated_with_trailing(cx, Comma, token::CloseParen, |cx| parse_expr(cx, true))?;
1535        cx.expect(token::CloseParen)?;
1536        if exprs.len() == 1 && !trailing {
1537            Ok(exprs.remove(0))
1538        } else {
1539            Ok(Expr {
1540                kind: ExprKind::Tuple(exprs),
1541                node_id: cx.next_node_id(),
1542                span: cx.mk_span(lo, cx.hi()),
1543            })
1544        }
1545    } else if lookahead.advance_if(token::Pound) {
1546        // #{ ⟨expr⟩,* }
1547        let lo = cx.lo();
1548        let exprs = braces(cx, Comma, |cx| parse_expr(cx, true))?;
1549        let hi = cx.hi();
1550        let kind = ExprKind::SetLiteral(exprs);
1551        Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1552    } else if lookahead.peek(NonReserved) {
1553        let path = parse_expr_path(cx)?;
1554        let kind = if allow_struct && cx.peek(token::OpenBrace) {
1555            // ⟨epath⟩ { ⟨constructor_arg⟩,* }
1556            let args = braces(cx, Comma, parse_constructor_arg)?;
1557            ExprKind::Constructor(Some(path), args)
1558        } else {
1559            // ⟨epath⟩
1560            ExprKind::Path(path)
1561        };
1562        let hi = cx.hi();
1563        Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1564    } else if allow_struct && lookahead.peek(token::OpenBrace) {
1565        // { ⟨constructor_arg⟩,* }
1566        let args = braces(cx, Comma, parse_constructor_arg)?;
1567        let hi = cx.hi();
1568        Ok(Expr {
1569            kind: ExprKind::Constructor(None, args),
1570            node_id: cx.next_node_id(),
1571            span: cx.mk_span(lo, hi),
1572        })
1573    } else if lookahead.advance_if(LAngle) {
1574        // <⟨ty⟩ as ⟨path⟩> :: ⟨ident⟩
1575        let lo = cx.lo();
1576        let qself = parse_type(cx)?;
1577        cx.expect(kw::As)?;
1578        let path = parse_path(cx)?;
1579        cx.expect(RAngle)?;
1580        cx.expect(token::PathSep)?;
1581        let name = parse_ident(cx)?;
1582        let hi = cx.hi();
1583        let kind = ExprKind::AssocReft(Box::new(qself), path, name);
1584        Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1585    } else if lookahead.peek(token::OpenBracket) {
1586        parse_prim_uif(cx)
1587    } else if lookahead.peek(kw::Exists) || lookahead.peek(kw::Forall) {
1588        parse_quantifier(cx)
1589    } else {
1590        Err(lookahead.into_error())
1591    }
1592}
1593
1594fn parse_prim_uif(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1595    let lo = cx.lo();
1596    cx.expect(token::OpenBracket)?;
1597    let op = parse_binop(cx)?;
1598    cx.expect(token::CloseBracket)?;
1599    let hi = cx.hi();
1600    Ok(Expr { kind: ExprKind::PrimUIF(op), node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1601}
1602
1603/// ```text
1604/// ⟨quant⟩ := forall ⟨refine_param⟩ in ⟨int⟩..⟨int⟩ ⟨block⟩
1605///          | exists ⟨refine_param⟩ in ⟨int⟩..⟨int⟩ ⟨block⟩
1606///          | forall ⟨refine_param⟩                 ⟨block⟩
1607///          | exists ⟨refine_param⟩                 ⟨block⟩
1608/// ```
1609fn parse_quantifier(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1610    let lo = cx.lo();
1611    let mut lookahead = cx.lookahead1();
1612    let quant = if lookahead.advance_if(kw::Forall) {
1613        QuantKind::Forall
1614    } else if lookahead.advance_if(kw::Exists) {
1615        QuantKind::Exists
1616    } else {
1617        return Err(lookahead.into_error());
1618    };
1619    let param = parse_refine_param(cx, RequireSort::Maybe)?;
1620
1621    let mut lookahead = cx.lookahead1();
1622    let dom = if lookahead.peek(kw::In) {
1623        cx.expect(kw::In)?;
1624        let start = parse_int(cx)?;
1625        cx.expect(token::DotDot)?;
1626        let end = parse_int(cx)?;
1627        Some(start..end)
1628    } else {
1629        None
1630    };
1631    let body = parse_block(cx)?;
1632    let hi = cx.hi();
1633    let kind = ExprKind::Quant(quant, param, dom, Box::new(body));
1634    Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1635}
1636
1637/// ```text
1638/// ⟨constructor_arg⟩ :=  ⟨ident⟩ : ⟨expr⟩ |  ..
1639/// ```
1640fn parse_constructor_arg(cx: &mut ParseCtxt) -> ParseResult<ConstructorArg> {
1641    let lo = cx.lo();
1642    let mut lookahead = cx.lookahead1();
1643    if lookahead.peek(NonReserved) {
1644        let ident = parse_ident(cx)?;
1645        cx.expect(token::Colon)?;
1646        let expr = parse_refine_arg(cx)?;
1647        let hi = cx.hi();
1648        Ok(ConstructorArg::FieldExpr(FieldExpr {
1649            ident,
1650            expr,
1651            node_id: cx.next_node_id(),
1652            span: cx.mk_span(lo, hi),
1653        }))
1654    } else if lookahead.advance_if(token::DotDot) {
1655        let spread = parse_expr(cx, true)?;
1656        let hi = cx.hi();
1657        Ok(ConstructorArg::Spread(Spread {
1658            expr: spread,
1659            node_id: cx.next_node_id(),
1660            span: cx.mk_span(lo, hi),
1661        }))
1662    } else {
1663        Err(lookahead.into_error())
1664    }
1665}
1666
1667/// `⟨epath⟩ := ⟨ident⟩ ⟨ :: ⟨ident⟩ ⟩*`
1668fn parse_expr_path(cx: &mut ParseCtxt) -> ParseResult<ExprPath> {
1669    let lo = cx.lo();
1670    let segments = sep1(cx, token::PathSep, parse_expr_path_segment)?;
1671    let hi = cx.hi();
1672    Ok(ExprPath { segments, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1673}
1674
1675fn parse_expr_path_segment(cx: &mut ParseCtxt) -> ParseResult<ExprPathSegment> {
1676    Ok(ExprPathSegment { ident: parse_ident(cx)?, node_id: cx.next_node_id() })
1677}
1678
1679/// `⟨if_expr⟩ := if ⟨expr⟩ ⟨block⟩ ⟨ else if ⟨expr⟩ ⟨block⟩ ⟩* else ⟨block⟩`
1680///
1681/// The `⟨expr⟩` in conditions is parsed with `allow_struct = false`
1682fn parse_if_expr(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1683    let mut branches = vec![];
1684
1685    loop {
1686        let lo = cx.lo();
1687        cx.expect(kw::If)?;
1688        let cond = parse_expr(cx, false)?;
1689        let then_ = parse_block(cx)?;
1690        branches.push((lo, cond, then_));
1691        cx.expect(kw::Else)?;
1692
1693        if !cx.peek(kw::If) {
1694            break;
1695        }
1696    }
1697    let mut else_ = parse_block(cx)?;
1698
1699    let hi = cx.hi();
1700    while let Some((lo, cond, then_)) = branches.pop() {
1701        else_ = Expr {
1702            kind: ExprKind::IfThenElse(Box::new([cond, then_, else_])),
1703            node_id: cx.next_node_id(),
1704            span: cx.mk_span(lo, hi),
1705        };
1706    }
1707    Ok(else_)
1708}
1709
1710/// `⟨block⟩ := { ⟨block_expr⟩ }`
1711fn parse_block(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1712    delimited(cx, Brace, parse_block_expr)
1713}
1714
1715/// `⟨block_expr⟩ = ⟨let_decl⟩* ⟨expr⟩`
1716fn parse_block_expr(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1717    let lo = cx.lo();
1718    let decls = repeat_while(cx, kw::Let, parse_let_decl)?;
1719    let body = parse_expr(cx, true)?;
1720    let hi = cx.hi();
1721
1722    if decls.is_empty() {
1723        Ok(body)
1724    } else {
1725        let kind = ExprKind::Block(decls, Box::new(body));
1726        Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1727    }
1728}
1729
1730/// `⟨let_decl⟩ := let ⟨refine_param⟩ = ⟨expr⟩ ;`
1731fn parse_let_decl(cx: &mut ParseCtxt) -> ParseResult<LetDecl> {
1732    cx.expect(kw::Let)?;
1733    let param = parse_refine_param(cx, RequireSort::Maybe)?;
1734    cx.expect(token::Eq)?;
1735    let init = parse_expr(cx, true)?;
1736    cx.expect(token::Semi)?;
1737    Ok(LetDecl { param, init })
1738}
1739
1740/// ```text
1741/// ⟨lit⟩ := ⟨a Rust literal like an integer or a boolean⟩
1742/// ```
1743fn parse_lit(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1744    if let Token { kind: token::Literal(lit), lo, hi } = cx.at(0) {
1745        cx.advance();
1746        Ok(Expr {
1747            kind: ExprKind::Literal(lit),
1748            node_id: cx.next_node_id(),
1749            span: cx.mk_span(lo, hi),
1750        })
1751    } else {
1752        Err(cx.unexpected_token(vec![AnyLit.expected()]))
1753    }
1754}
1755
1756fn parse_ident(cx: &mut ParseCtxt) -> ParseResult<Ident> {
1757    if let Token { kind: token::Ident(name, is_raw), lo, hi } = cx.at(0)
1758        && (!cx.is_reserved(name) || is_raw == IdentIsRaw::Yes)
1759    {
1760        cx.advance();
1761        return Ok(Ident { name, span: cx.mk_span(lo, hi) });
1762    }
1763    Err(cx.unexpected_token(vec![NonReserved.expected()]))
1764}
1765
1766fn parse_int<T: FromStr>(cx: &mut ParseCtxt) -> ParseResult<T> {
1767    if let token::Literal(lit) = cx.at(0).kind
1768        && let Lit { kind: LitKind::Integer, symbol, suffix: None, .. } = lit
1769        && let Ok(value) = symbol.as_str().parse::<T>()
1770    {
1771        cx.advance();
1772        return Ok(value);
1773    }
1774
1775    Err(cx.unexpected_token(vec![Expected::Str(std::any::type_name::<T>())]))
1776}
1777
1778/// ```text
1779/// ⟨sort⟩ :=  ⟨base_sort⟩
1780///         |  ( ⟨base_sort⟩,* ) -> ⟨base_sort⟩
1781///         |  ⟨base_sort⟩ -> ⟨base_sort⟩
1782/// ```
1783fn parse_sort(cx: &mut ParseCtxt) -> ParseResult<Sort> {
1784    if cx.peek(token::OpenParen) {
1785        // ( ⟨base_sort⟩,* ) -> ⟨base_sort⟩ | ( ⟨base_sort⟩,* )
1786        let inputs = parens(cx, Comma, parse_base_sort)?;
1787        if cx.advance_if(token::RArrow) {
1788            // ( ⟨base_sort⟩,* ) -> ⟨base_sort⟩
1789            let output = parse_base_sort(cx)?;
1790            Ok(Sort::Func { inputs, output })
1791        } else {
1792            // ( ⟨base_sort⟩,* )
1793            Ok(Sort::Base(BaseSort::Tuple(inputs)))
1794        }
1795    } else {
1796        let bsort = parse_base_sort(cx)?;
1797        if cx.advance_if(token::RArrow) {
1798            // ⟨base_sort⟩ -> ⟨base_sort⟩
1799            let output = parse_base_sort(cx)?;
1800            Ok(Sort::Func { inputs: vec![bsort], output })
1801        } else {
1802            // ⟨base_sort⟩
1803            Ok(Sort::Base(bsort))
1804        }
1805    }
1806}
1807
1808/// ```text
1809/// ⟨base_sort⟩ := bitvec < ⟨u32⟩ >
1810///              | ( ⟨base_sort⟩,* )
1811///              | ⟨sort_path⟩ < ⟨base_sort⟩,* >
1812///              | < ⟨ty⟩ as ⟨path⟩ > :: ⟨segment⟩
1813/// ⟨sort_path⟩ := ⟨ident⟩ ⟨ :: ⟨ident⟩ ⟩* < (⟨base_sort⟩,*) >
1814/// ```
1815fn parse_base_sort(cx: &mut ParseCtxt) -> ParseResult<BaseSort> {
1816    if cx.advance_if(kw::Bitvec) {
1817        // bitvec < ⟨u32⟩ >
1818        cx.expect(LAngle)?;
1819        let len = parse_int(cx)?;
1820        cx.expect(RAngle)?;
1821        Ok(BaseSort::BitVec(len))
1822    } else if cx.peek(token::OpenParen) {
1823        // ( ⟨base_sort⟩,* )
1824        let sorts = parens(cx, Comma, parse_base_sort)?;
1825        Ok(BaseSort::Tuple(sorts))
1826    } else if cx.advance_if(LAngle) {
1827        // < ⟨ty⟩ as ⟨path⟩ > :: ⟨segment⟩
1828        let qself = parse_type(cx)?;
1829        cx.expect(kw::As)?;
1830        let mut path = parse_path(cx)?;
1831        cx.expect(RAngle)?;
1832        cx.expect(token::PathSep)?;
1833        path.segments.push(parse_segment(cx)?);
1834        Ok(BaseSort::SortOf(Box::new(qself), path))
1835    } else {
1836        // ⟨sort_path⟩ < ⟨base_sort⟩,* >
1837        let segments = sep1(cx, token::PathSep, parse_ident)?;
1838        let args = opt_angle(cx, Comma, parse_base_sort)?;
1839        let path = SortPath { segments, args, node_id: cx.next_node_id() };
1840        Ok(BaseSort::Path(path))
1841    }
1842}
1843
1844// Reference: https://doc.rust-lang.org/reference/expressions.html#expression-precedence
1845#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
1846enum Precedence {
1847    /// <=>
1848    Iff,
1849    /// =>
1850    Implies,
1851    /// ||
1852    Or,
1853    /// &&
1854    And,
1855    /// == != < > <= >=
1856    Compare,
1857    /// |
1858    BitOr,
1859    /// ^
1860    BitXor,
1861    /// &
1862    BitAnd,
1863    /// << >>
1864    Shift,
1865    /// + -
1866    Sum,
1867    /// * / %
1868    Product,
1869    /// unary - and !
1870    Prefix,
1871}
1872
1873enum Associativity {
1874    Right,
1875    Left,
1876    None,
1877}
1878
1879impl Precedence {
1880    const MIN: Self = Precedence::Iff;
1881
1882    fn of_binop(op: &BinOp) -> Precedence {
1883        match op {
1884            BinOp::Iff => Precedence::Iff,
1885            BinOp::Imp => Precedence::Implies,
1886            BinOp::Or => Precedence::Or,
1887            BinOp::And => Precedence::And,
1888            BinOp::Eq | BinOp::Ne | BinOp::Gt | BinOp::Ge | BinOp::Lt | BinOp::Le => {
1889                Precedence::Compare
1890            }
1891            BinOp::BitOr => Precedence::BitOr,
1892            BinOp::BitXor => Precedence::BitXor,
1893            BinOp::BitAnd => Precedence::BitAnd,
1894            BinOp::BitShl | BinOp::BitShr => Precedence::Shift,
1895            BinOp::Add | BinOp::Sub => Precedence::Sum,
1896            BinOp::Mul | BinOp::Div | BinOp::Mod => Precedence::Product,
1897        }
1898    }
1899
1900    fn next(self) -> Precedence {
1901        match self {
1902            Precedence::Iff => Precedence::Implies,
1903            Precedence::Implies => Precedence::Or,
1904            Precedence::Or => Precedence::And,
1905            Precedence::And => Precedence::Compare,
1906            Precedence::Compare => Precedence::BitOr,
1907            Precedence::BitOr => Precedence::BitXor,
1908            Precedence::BitXor => Precedence::BitAnd,
1909            Precedence::BitAnd => Precedence::Shift,
1910            Precedence::Shift => Precedence::Sum,
1911            Precedence::Sum => Precedence::Product,
1912            Precedence::Product => Precedence::Prefix,
1913            Precedence::Prefix => Precedence::Prefix,
1914        }
1915    }
1916
1917    fn associativity(self) -> Associativity {
1918        match self {
1919            Precedence::Or
1920            | Precedence::And
1921            | Precedence::BitOr
1922            | Precedence::BitXor
1923            | Precedence::BitAnd
1924            | Precedence::Shift
1925            | Precedence::Sum
1926            | Precedence::Product => Associativity::Left,
1927            Precedence::Compare | Precedence::Iff => Associativity::None,
1928            Precedence::Implies | Precedence::Prefix => Associativity::Right,
1929        }
1930    }
1931}