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