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
33enum SyntaxAttr {
41 Reft,
43 Invariant(Expr),
45 RefinedBy(RefineParams),
47 Hide,
54 Opaque,
56 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
114pub(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
139fn parse_reason(cx: &mut ParseCtxt) -> ParseResult {
143 cx.expect(sym::reason)?;
144 cx.expect(token::Eq)?;
145 cx.expect(AnyLit)
146}
147
148pub(crate) fn parse_ident_list(cx: &mut ParseCtxt) -> ParseResult<Vec<Ident>> {
152 punctuated_until(cx, Comma, token::Eof, parse_ident)
153}
154
155pub(crate) fn parse_flux_items(cx: &mut ParseCtxt) -> ParseResult<Vec<FluxItem>> {
159 until(cx, token::Eof, parse_flux_item)
160}
161
162fn 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
189pub(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
197pub(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
226fn 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
236fn 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
308fn 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
325fn 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
342fn 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
370fn 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 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
463fn 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
488fn 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
503fn 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 ¶ms {
523 fvars.remove(¶m.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 wildcards.resize(params.len(), false);
537
538 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
557fn 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
569fn 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
578fn parse_primop_property(cx: &mut ParseCtxt) -> ParseResult<PrimOpProp> {
582 let lo = cx.lo();
583 cx.expect(kw::Property)?;
584
585 let name = parse_ident(cx)?;
587
588 cx.expect(token::OpenBracket)?;
590 let op = parse_binop(cx)?;
591 cx.expect(token::CloseBracket)?;
592
593 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
602fn 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
612fn 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
639fn 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
666fn 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
681pub(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
688pub(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
717fn 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
731fn 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 let locs = ensures
797 .iter()
798 .filter_map(|ens| if let Ensures::Type(ident, _, _) = ens { Some(ident) } else { None })
799 .collect::<HashSet<_>>();
800 let mut res = vec![];
802 for input in inputs {
803 if let FnInput::Ty(Some(ident), _, _) = &input
804 && locs.contains(&ident)
805 {
806 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 res.push(input);
817 }
818 }
819 Ok(res)
820}
821
822pub(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, })
860}
861
862fn 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
877fn 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
890fn 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
905fn parse_ensures_clause(cx: &mut ParseCtxt) -> ParseResult<Ensures> {
910 if cx.peek2(NonReserved, token::Colon) {
911 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 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
938fn 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
950fn 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 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 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 let pred = delimited(cx, Brace, |cx| parse_expr(cx, true))?;
973 Ok(FnInput::Constr(bind, path, pred, cx.next_node_id()))
974 } else {
975 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 Ok(FnInput::Ty(Some(bind), parse_type(cx)?, cx.next_node_id()))
983 }
984 } else {
985 Ok(FnInput::Ty(None, parse_type(cx)?, cx.next_node_id()))
987 }
988}
989
990fn 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
1025pub(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 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 parse_general_exists(cx)
1062 } else {
1063 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 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 let mutbl = if cx.advance_if(kw::Mut) {
1077 Mutability::Mut
1078 } else {
1079 cx.expect(kw::Const)?;
1080 Mutability::Not
1081 };
1082 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 let len = parse_const_arg(cx)?;
1099 cx.expect(token::CloseBracket)?;
1100 TyKind::Array(Box::new(ty), len)
1101 } else {
1102 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 TyKind::ImplTrait(cx.next_node_id(), parse_generic_bounds(cx)?)
1111 } else if lookahead.peek(NonReserved) {
1112 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 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
1127fn 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
1147fn 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
1158fn parse_bty_rhs(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
1164 let lo = bty.span.lo();
1165 if cx.peek(token::OpenBracket) {
1166 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 parse_bty_exists(cx, bty)
1174 } else {
1175 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
1182fn 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
1274fn 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
1286fn parse_segments(cx: &mut ParseCtxt) -> ParseResult<Vec<PathSegment>> {
1290 sep1(cx, token::PathSep, parse_segment)
1291}
1292
1293fn 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
1302fn 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
1317fn parse_refine_arg(cx: &mut ParseCtxt) -> ParseResult<RefineArg> {
1324 let lo = cx.lo();
1325 let arg = if cx.advance_if(token::At) {
1326 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 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 RefineArg::Expr(parse_expr(cx, true)?)
1346 };
1347 Ok(arg)
1348}
1349
1350enum RequireSort {
1352 Yes,
1354 Maybe,
1356 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
1377fn 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
1391fn 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
1403fn 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
1453fn 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
1469fn 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 cx.advance();
1485 ExprKind::Dot(Box::new(e), Ident { name, span: cx.mk_span(lo, hi) })
1486 } else {
1487 let field = parse_ident(cx)?;
1489 ExprKind::Dot(Box::new(e), field)
1490 }
1491 } else if cx.peek(token::OpenParen) {
1492 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
1504fn 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 parse_if_expr(cx)
1523 } else if lookahead.peek(AnyLit) {
1524 parse_lit(cx)
1526 } else if lookahead.advance_if(token::OpenParen) {
1527 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 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 let args = braces(cx, Comma, parse_constructor_arg)?;
1552 ExprKind::Constructor(Some(path), args)
1553 } else {
1554 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 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 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
1598fn 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
1632fn 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
1662fn 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
1674fn 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
1705fn parse_block(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1707 delimited(cx, Brace, parse_block_expr)
1708}
1709
1710fn 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
1725fn 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
1735fn 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
1773fn parse_sort(cx: &mut ParseCtxt) -> ParseResult<Sort> {
1779 if cx.peek(token::OpenParen) {
1780 let inputs = parens(cx, Comma, parse_base_sort)?;
1782 if cx.advance_if(token::RArrow) {
1783 let output = parse_base_sort(cx)?;
1785 Ok(Sort::Func { inputs, output })
1786 } else {
1787 Ok(Sort::Base(BaseSort::Tuple(inputs)))
1789 }
1790 } else {
1791 let bsort = parse_base_sort(cx)?;
1792 if cx.advance_if(token::RArrow) {
1793 let output = parse_base_sort(cx)?;
1795 Ok(Sort::Func { inputs: vec![bsort], output })
1796 } else {
1797 Ok(Sort::Base(bsort))
1799 }
1800 }
1801}
1802
1803fn parse_base_sort(cx: &mut ParseCtxt) -> ParseResult<BaseSort> {
1811 if cx.advance_if(kw::Bitvec) {
1812 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 let sorts = parens(cx, Comma, parse_base_sort)?;
1820 Ok(BaseSort::Tuple(sorts))
1821 } else if cx.advance_if(LAngle) {
1822 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 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#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
1841enum Precedence {
1842 Iff,
1844 Implies,
1846 Or,
1848 And,
1850 Compare,
1852 BitOr,
1854 BitXor,
1856 BitAnd,
1858 Shift,
1860 Sum,
1862 Product,
1864 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}