1pub(crate) mod lookahead;
2mod utils;
3use std::{collections::HashSet, str::FromStr, vec};
4
5use lookahead::{AnyLit, LAngle, NonReserved, RAngle};
6use rustc_ast::token::Lit;
7use rustc_data_structures::unord::UnordSet;
8use rustc_span::{Symbol, sym::Output};
9use utils::{
10 angle, braces, brackets, delimited, opt_angle, parens, punctuated_until,
11 punctuated_with_trailing, repeat_while, sep1, until,
12};
13
14use crate::{
15 ParseCtxt, ParseError, ParseResult,
16 parser::lookahead::{AnyOf, Expected, PeekExpected},
17 surface::{
18 self, Async,
19 Attr::{self},
20 BaseSort, BaseTy, BaseTyKind, BinOp, BindKind, ConstArg, ConstArgKind, ConstructorArg,
21 DetachedInherentImpl, DetachedItem, DetachedItemKind, DetachedSpecs, DetachedTrait,
22 DetachedTraitImpl, Ensures, EnumDef, Expr, ExprKind, ExprPath, ExprPathSegment, FieldExpr,
23 FluxItem, FnInput, FnOutput, FnRetTy, FnSig, GenericArg, GenericArgKind, GenericBounds,
24 GenericParam, Generics, Ident, ImplAssocReft, Indices, LetDecl, LitKind, Mutability,
25 ParamMode, Path, PathSegment, PrimOpProp, Qualifier, QualifierKind, QuantKind, RefineArg,
26 RefineParam, RefineParams, Requires, Sort, SortDecl, SortPath, SpecFunc, Spread,
27 StaticInfo, StructDef, TraitAssocReft, TraitRef, Trusted, Ty, TyAlias, TyKind, UnOp,
28 UseTree, UseTreeKind, VariantDef, VariantRet, WhereBoundPredicate,
29 },
30 symbols::{kw, sym},
31 token::{self, Comma, Delimiter::*, IdentIsRaw, Or, Token, TokenKind},
32};
33
34enum SyntaxAttr {
42 Reft,
44 Invariant(Expr),
46 RefinedBy(RefineParams),
48 Hide,
55 Opaque,
57 NoPanicIf(Expr),
59}
60
61#[derive(Default)]
62struct ParsedAttrs {
63 normal: Vec<Attr>,
64 syntax: Vec<SyntaxAttr>,
65}
66
67impl ParsedAttrs {
68 fn is_reft(&self) -> bool {
69 self.syntax
70 .iter()
71 .any(|attr| matches!(attr, SyntaxAttr::Reft))
72 }
73
74 fn is_hide(&self) -> bool {
75 self.syntax
76 .iter()
77 .any(|attr| matches!(attr, SyntaxAttr::Hide))
78 }
79
80 fn is_opaque(&self) -> bool {
81 self.syntax
82 .iter()
83 .any(|attr| matches!(attr, SyntaxAttr::Opaque))
84 }
85
86 fn refined_by(&mut self) -> Option<RefineParams> {
87 let pos = self
88 .syntax
89 .iter()
90 .position(|x| matches!(x, SyntaxAttr::RefinedBy(_)))?;
91 if let SyntaxAttr::RefinedBy(params) = self.syntax.remove(pos) {
92 Some(params)
93 } else {
94 None
95 }
96 }
97
98 fn no_panic_if(&mut self) -> Option<Expr> {
99 let pos = self
100 .syntax
101 .iter()
102 .position(|x| matches!(x, SyntaxAttr::NoPanicIf(_)))?;
103 if let SyntaxAttr::NoPanicIf(expr) = self.syntax.remove(pos) { Some(expr) } else { None }
104 }
105
106 fn invariant(&mut self) -> Option<Expr> {
107 let pos = self
108 .syntax
109 .iter()
110 .position(|x| matches!(x, SyntaxAttr::Invariant(_)))?;
111 if let SyntaxAttr::Invariant(exp) = self.syntax.remove(pos) { Some(exp) } else { None }
112 }
113}
114
115pub(crate) fn parse_yes_or_no_with_reason(cx: &mut ParseCtxt) -> ParseResult<bool> {
121 let mut lookahead = cx.lookahead1();
122 if lookahead.advance_if(sym::yes) {
123 if cx.advance_if(token::Comma) {
124 parse_reason(cx)?;
125 }
126 Ok(true)
127 } else if lookahead.advance_if(sym::no) {
128 if cx.advance_if(token::Comma) {
129 parse_reason(cx)?;
130 }
131 Ok(false)
132 } else if lookahead.peek(sym::reason) {
133 parse_reason(cx)?;
134 Ok(true)
135 } else {
136 Err(lookahead.into_error())
137 }
138}
139
140fn parse_reason(cx: &mut ParseCtxt) -> ParseResult {
144 cx.expect(sym::reason)?;
145 cx.expect(token::Eq)?;
146 cx.expect(AnyLit)
147}
148
149pub(crate) fn parse_ident_list(cx: &mut ParseCtxt) -> ParseResult<Vec<Ident>> {
153 punctuated_until(cx, Comma, token::Eof, parse_ident)
154}
155
156pub(crate) fn parse_flux_items(cx: &mut ParseCtxt) -> ParseResult<Vec<FluxItem>> {
160 until(cx, token::Eof, parse_flux_item)
161}
162
163fn parse_flux_item(cx: &mut ParseCtxt) -> ParseResult<FluxItem> {
171 let mut lookahead = cx.lookahead1();
172 if lookahead.peek(token::Pound) || lookahead.peek(kw::Fn) {
173 parse_reft_func(cx).map(FluxItem::FuncDef)
174 } else if lookahead.peek(kw::Local)
175 || lookahead.peek(kw::Invariant)
176 || lookahead.peek(kw::Qualifier)
177 {
178 parse_qualifier(cx).map(FluxItem::Qualifier)
179 } else if lookahead.peek(kw::Opaque) {
180 parse_sort_decl(cx).map(FluxItem::SortDecl)
181 } else if lookahead.peek(kw::Property) {
182 parse_primop_property(cx).map(FluxItem::PrimOpProp)
183 } else if lookahead.peek(kw::Use) {
184 parse_use_item(cx).map(FluxItem::Use)
185 } else {
186 Err(lookahead.into_error())
187 }
188}
189
190pub(crate) fn parse_detached_specs(cx: &mut ParseCtxt) -> ParseResult<surface::DetachedSpecs> {
194 let items = until(cx, token::Eof, parse_detached_item)?;
195 Ok(surface::DetachedSpecs { items })
196}
197
198pub(crate) fn parse_detached_item(cx: &mut ParseCtxt) -> ParseResult<DetachedItem> {
206 let attrs = parse_attrs(cx)?;
207 let mut lookahead = cx.lookahead1();
208 if lookahead.peek(kw::Fn) {
209 Ok(parse_detached_fn_sig(cx, attrs)?.map_kind(DetachedItemKind::FnSig))
210 } else if lookahead.peek(kw::Mod) {
211 parse_detached_mod(cx)
212 } else if lookahead.peek(kw::Struct) {
213 parse_detached_struct(cx, attrs)
214 } else if lookahead.peek(kw::Enum) {
215 parse_detached_enum(cx, attrs)
216 } else if lookahead.peek(kw::Impl) {
217 parse_detached_impl(cx, attrs)
218 } else if lookahead.peek(kw::Trait) {
219 parse_detached_trait(cx, attrs)
220 } else if lookahead.peek(kw::Static) {
221 parse_detached_static(cx, attrs)
222 } else {
223 Err(lookahead.into_error())
224 }
225}
226
227fn parse_detached_field(cx: &mut ParseCtxt) -> ParseResult<(Ident, Ty)> {
231 let ident = parse_ident(cx)?;
232 cx.expect(token::Colon)?;
233 let ty = parse_type(cx)?;
234 Ok((ident, ty))
235}
236
237fn parse_detached_enum(cx: &mut ParseCtxt, mut attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
241 cx.expect(kw::Enum)?;
242 let path = parse_expr_path(cx)?;
243 let generics = Some(parse_opt_generics(cx)?);
244 let refined_by = attrs.refined_by();
245 let invariants = attrs.invariant().into_iter().collect();
246 let variants = braces(cx, Comma, |cx| parse_variant(cx, true))?
247 .into_iter()
248 .map(Some)
249 .collect();
250 let enum_def = EnumDef { generics, refined_by, variants, invariants, reflected: false };
251 Ok(DetachedItem {
252 attrs: attrs.normal,
253 path,
254 kind: DetachedItemKind::Enum(enum_def),
255 node_id: cx.next_node_id(),
256 })
257}
258
259fn parse_detached_struct(cx: &mut ParseCtxt, mut attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
260 cx.expect(kw::Struct)?;
261 let path = parse_expr_path(cx)?;
262 let generics = Some(parse_opt_generics(cx)?);
263 let refined_by = attrs.refined_by();
264 let opaque = attrs.is_opaque();
265 let invariants = attrs.invariant().into_iter().collect();
266 let fields = if cx.peek(token::OpenBrace) {
267 braces(cx, Comma, parse_detached_field)?
268 .into_iter()
269 .map(|(_, ty)| Some(ty))
270 .collect()
271 } else if cx.peek(token::OpenParen) {
272 parens(cx, Comma, parse_type)?
273 .into_iter()
274 .map(Some)
275 .collect()
276 } else {
277 cx.expect(token::Semi)?;
278 vec![]
279 };
280 let struct_def = StructDef { generics, opaque, refined_by, invariants, fields };
281 Ok(DetachedItem {
282 attrs: attrs.normal,
283 path,
284 kind: DetachedItemKind::Struct(struct_def),
285 node_id: cx.next_node_id(),
286 })
287}
288
289fn ident_path(cx: &mut ParseCtxt, ident: Ident) -> ExprPath {
290 let span = ident.span;
291 let segments = vec![ExprPathSegment { ident, node_id: cx.next_node_id() }];
292 ExprPath { segments, span, node_id: cx.next_node_id() }
293}
294
295fn parse_detached_fn_sig(
296 cx: &mut ParseCtxt,
297 mut attrs: ParsedAttrs,
298) -> ParseResult<DetachedItem<FnSig>> {
299 let mut fn_sig = parse_fn_sig(cx, token::Semi)?;
300 fn_sig.no_panic = attrs.no_panic_if();
301 let span = fn_sig.span;
302 let ident = fn_sig
303 .ident
304 .ok_or(ParseError { kind: crate::ParseErrorKind::InvalidDetachedSpec, span })?;
305 let path = ident_path(cx, ident);
306 Ok(DetachedItem { attrs: attrs.normal, path, kind: fn_sig, node_id: cx.next_node_id() })
307}
308
309fn parse_detached_static(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
313 cx.expect(kw::Static)?;
314 let path = parse_expr_path(cx)?;
315 cx.expect(token::Colon)?;
316 let ty = parse_type(cx)?;
317 cx.expect(token::Semi)?;
318 Ok(DetachedItem {
319 attrs: attrs.normal,
320 path,
321 kind: DetachedItemKind::Static(StaticInfo { ty }),
322 node_id: cx.next_node_id(),
323 })
324}
325
326fn parse_detached_mod(cx: &mut ParseCtxt) -> ParseResult<DetachedItem> {
330 cx.expect(kw::Mod)?;
331 let path = parse_expr_path(cx)?;
332 cx.expect(TokenKind::open_delim(Brace))?;
333 let items = until(cx, TokenKind::close_delim(Brace), parse_detached_item)?;
334 cx.expect(TokenKind::close_delim(Brace))?;
335 Ok(DetachedItem {
336 attrs: vec![],
337 path,
338 kind: DetachedItemKind::Mod(DetachedSpecs { items }),
339 node_id: cx.next_node_id(),
340 })
341}
342
343fn parse_detached_trait(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
347 cx.expect(kw::Trait)?;
348 let path = parse_expr_path(cx)?;
349 let _generics = parse_opt_generics(cx)?;
350 cx.expect(TokenKind::open_delim(Brace))?;
351
352 let mut items = vec![];
353 let mut refts = vec![];
354 while !cx.peek(TokenKind::close_delim(Brace)) {
355 let assoc_item_attrs = parse_attrs(cx)?;
356 if assoc_item_attrs.is_reft() {
357 refts.push(parse_trait_assoc_reft(cx)?);
358 } else {
359 items.push(parse_detached_fn_sig(cx, assoc_item_attrs)?);
360 }
361 }
362 cx.expect(TokenKind::close_delim(Brace))?;
363 Ok(DetachedItem {
364 attrs: attrs.normal,
365 path,
366 kind: DetachedItemKind::Trait(DetachedTrait { items, refts }),
367 node_id: cx.next_node_id(),
368 })
369}
370
371fn parse_detached_impl(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
375 let lo = cx.lo();
376 cx.expect(kw::Impl)?;
377 let hi = cx.hi();
378 let span = cx.mk_span(lo, hi);
379 let outer_path = parse_expr_path(cx)?;
380 let _generics = parse_opt_generics(cx)?;
381 let inner_path = if cx.advance_if(kw::For) {
382 let path = parse_expr_path(cx)?;
383 let _generics = parse_opt_generics(cx)?;
384 Some(path)
385 } else {
386 None
387 };
388 cx.expect(TokenKind::open_delim(Brace))?;
389
390 let mut items = vec![];
391 let mut refts = vec![];
392 while !cx.peek(TokenKind::close_delim(Brace)) {
393 let assoc_item_attrs = parse_attrs(cx)?;
395 if assoc_item_attrs.is_reft() && inner_path.is_some() {
396 refts.push(parse_impl_assoc_reft(cx)?);
397 } else {
398 items.push(parse_detached_fn_sig(cx, assoc_item_attrs)?);
399 }
400 }
401 cx.expect(TokenKind::close_delim(Brace))?;
402 if let Some(path) = inner_path {
403 Ok(DetachedItem {
404 attrs: attrs.normal,
405 path,
406 kind: DetachedItemKind::TraitImpl(DetachedTraitImpl {
407 trait_: outer_path,
408 items,
409 refts,
410 span,
411 }),
412 node_id: cx.next_node_id(),
413 })
414 } else {
415 Ok(DetachedItem {
416 attrs: attrs.normal,
417 path: outer_path,
418 kind: DetachedItemKind::InherentImpl(DetachedInherentImpl { items, span }),
419 node_id: cx.next_node_id(),
420 })
421 }
422}
423
424fn parse_attr(cx: &mut ParseCtxt, attrs: &mut ParsedAttrs) -> ParseResult {
425 cx.expect(token::Pound)?;
426 cx.expect(token::OpenBracket)?;
427 let mut lookahead = cx.lookahead1();
428 if lookahead.advance_if(kw::Trusted) {
429 if cx.advance_if(token::OpenParen) {
430 parse_reason(cx)?;
431 cx.expect(token::CloseParen)?;
432 }
433 attrs.normal.push(Attr::Trusted(Trusted::Yes));
434 } else if lookahead.advance_if(sym::hide) {
435 attrs.syntax.push(SyntaxAttr::Hide);
436 } else if lookahead.advance_if(kw::Opaque) {
437 attrs.syntax.push(SyntaxAttr::Opaque);
438 } else if lookahead.advance_if(kw::Reft) {
439 attrs.syntax.push(SyntaxAttr::Reft);
440 } else if lookahead.advance_if(kw::RefinedBy) {
441 attrs
442 .syntax
443 .push(SyntaxAttr::RefinedBy(delimited(cx, Parenthesis, parse_refined_by)?));
444 } else if lookahead.advance_if(kw::Invariant) {
445 attrs
446 .syntax
447 .push(SyntaxAttr::Invariant(delimited(cx, Parenthesis, |cx| parse_expr(cx, true))?));
448 } else if lookahead.advance_if(sym::no_panic_if) {
449 attrs
450 .syntax
451 .push(SyntaxAttr::NoPanicIf(parse_expr(cx, true)?));
452 } else {
453 return Err(lookahead.into_error());
454 };
455 cx.expect(token::CloseBracket)
456}
457
458fn parse_attrs(cx: &mut ParseCtxt) -> ParseResult<ParsedAttrs> {
459 let mut attrs = ParsedAttrs::default();
460 repeat_while(cx, token::Pound, |cx| parse_attr(cx, &mut attrs))?;
461 Ok(attrs)
462}
463
464fn parse_reft_func(cx: &mut ParseCtxt) -> ParseResult<SpecFunc> {
472 let attrs = parse_attrs(cx)?;
473 let hide = attrs.is_hide();
474 cx.expect(kw::Fn)?;
475 let name = parse_ident(cx)?;
476 let sort_vars = opt_angle(cx, Comma, parse_ident)?;
477 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
478 cx.expect(token::RArrow)?;
479 let output = parse_sort(cx)?;
480 let body = if cx.peek(token::OpenBrace) {
481 Some(parse_block(cx)?)
482 } else {
483 cx.expect(token::Semi)?;
484 None
485 };
486 Ok(SpecFunc { name, sort_vars, params, output, body, hide })
487}
488
489fn parse_qualifier_kind(cx: &mut ParseCtxt) -> ParseResult<QualifierKind> {
494 let mut lookahead = cx.lookahead1();
495 if lookahead.advance_if(kw::Local) {
496 Ok(QualifierKind::Local)
497 } else if lookahead.advance_if(kw::Invariant) {
498 Ok(QualifierKind::Hint)
499 } else {
500 Ok(QualifierKind::Global)
501 }
502}
503
504fn parse_qualifier(cx: &mut ParseCtxt) -> ParseResult<Qualifier> {
510 let lo = cx.lo();
511 let kind = parse_qualifier_kind(cx)?;
512 cx.expect(kw::Qualifier)?;
513 let mut name = parse_ident(cx)?;
514 let (mut params, mut wildcards): (RefineParams, Vec<bool>) =
515 parens(cx, Comma, parse_qualifier_param)?
516 .into_iter()
517 .unzip();
518 let expr = parse_block(cx)?;
519 let hi = cx.hi();
520
521 if let QualifierKind::Hint = kind {
522 let explicit: UnordSet<_> = params.iter().map(|param| param.ident).collect();
525 params.extend(
526 expr.free_vars()
527 .into_iter()
528 .filter(|ident| !explicit.contains(ident))
529 .map(|ident| {
530 RefineParam {
531 ident,
532 sort: Sort::Infer,
533 mode: None,
534 span: ident.span,
535 node_id: cx.next_node_id(),
536 }
537 }),
538 );
539 wildcards.resize(params.len(), false);
542
543 let span = name.span;
548 let str = format!(
549 "{}_{}_{}_{}",
550 name.name.to_ident_string(),
551 span.lo().0,
552 span.hi().0,
553 cx.next_node_id().as_usize()
554 );
555 name = Ident { name: Symbol::intern(&str), ..name };
556 }
557
558 debug_assert_eq!(params.len(), wildcards.len());
559 Ok(Qualifier { name, params, wildcards, expr, span: cx.mk_span(lo, hi), kind })
560}
561
562fn parse_sort_decl(cx: &mut ParseCtxt) -> ParseResult<SortDecl> {
566 cx.expect(kw::Opaque)?;
567 cx.expect(kw::Sort)?;
568 let name = parse_ident(cx)?;
569 let sort_vars = opt_angle(cx, Comma, parse_ident)?;
570 cx.expect(token::Semi)?;
571 Ok(SortDecl { name, sort_vars })
572}
573
574fn parse_binop(cx: &mut ParseCtxt) -> ParseResult<BinOp> {
576 let (op, ntokens) = cx
577 .peek_binop()
578 .ok_or_else(|| cx.unexpected_token(vec![Expected::Str("binary operator")]))?;
579 cx.advance_by(ntokens);
580 Ok(op)
581}
582
583fn parse_primop_property(cx: &mut ParseCtxt) -> ParseResult<PrimOpProp> {
587 let lo = cx.lo();
588 cx.expect(kw::Property)?;
589
590 let name = parse_ident(cx)?;
592
593 cx.expect(token::OpenBracket)?;
595 let op = parse_binop(cx)?;
596 cx.expect(token::CloseBracket)?;
597
598 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::No))?;
600
601 let body = parse_block(cx)?;
602 let hi = cx.hi();
603
604 Ok(PrimOpProp { name, op, params, body, span: cx.mk_span(lo, hi) })
605}
606
607fn parse_use_item(cx: &mut ParseCtxt) -> ParseResult<UseTree> {
611 cx.expect(kw::Use)?;
612 let tree = parse_use_tree(cx)?;
613 cx.expect(token::Semi)?;
614 Ok(tree)
615}
616
617fn parse_use_tree(cx: &mut ParseCtxt) -> ParseResult<UseTree> {
621 let lo = cx.lo();
622 let mut segments = vec![parse_expr_path_segment(cx)?];
623 let mut hi = cx.hi();
624 let kind = loop {
625 if !cx.advance_if(token::PathSep) {
626 break UseTreeKind::Simple;
627 }
628 if cx.advance_if(token::OpenBrace) {
629 let items = punctuated_until(cx, token::Comma, token::CloseBrace, parse_use_tree)?;
630 cx.expect(token::CloseBrace)?;
631 break UseTreeKind::Nested(items);
632 }
633 segments.push(parse_expr_path_segment(cx)?);
634 hi = cx.hi();
635 };
636 let prefix = ExprPath { segments, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) };
637 Ok(UseTree { prefix, kind })
638}
639
640pub(crate) fn parse_trait_assoc_refts(cx: &mut ParseCtxt) -> ParseResult<Vec<TraitAssocReft>> {
641 until(cx, token::Eof, parse_trait_assoc_reft)
642}
643
644fn parse_trait_assoc_reft(cx: &mut ParseCtxt) -> ParseResult<TraitAssocReft> {
650 let lo = cx.lo();
651 let final_ = cx.advance_if(kw::Final);
652 cx.expect(kw::Fn)?;
653 let name = parse_ident(cx)?;
654 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
655 cx.expect(token::RArrow)?;
656 let output = parse_base_sort(cx)?;
657 let body = if cx.peek(token::OpenBrace) {
658 Some(parse_block(cx)?)
659 } else {
660 cx.advance_if(token::Semi);
661 None
662 };
663 let hi = cx.hi();
664 Ok(TraitAssocReft { name, params, output, body, span: cx.mk_span(lo, hi), final_ })
665}
666
667pub(crate) fn parse_impl_assoc_refts(cx: &mut ParseCtxt) -> ParseResult<Vec<ImplAssocReft>> {
668 until(cx, token::Eof, parse_impl_assoc_reft)
669}
670
671fn parse_impl_assoc_reft(cx: &mut ParseCtxt) -> ParseResult<ImplAssocReft> {
675 let lo = cx.lo();
676 cx.expect(kw::Fn)?;
677 let name = parse_ident(cx)?;
678 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
679 cx.expect(token::RArrow)?;
680 let output = parse_base_sort(cx)?;
681 let body = parse_block(cx)?;
682 let hi = cx.hi();
683 Ok(ImplAssocReft { name, params, output, body, span: cx.mk_span(lo, hi) })
684}
685
686pub(crate) fn parse_refined_by(cx: &mut ParseCtxt) -> ParseResult<RefineParams> {
690 punctuated_until(cx, Comma, token::Eof, |cx| parse_refine_param(cx, RequireSort::Yes))
691}
692
693pub(crate) fn parse_variant(cx: &mut ParseCtxt, ret_arrow: bool) -> ParseResult<VariantDef> {
699 let lo = cx.lo();
700 let mut fields = vec![];
701 let mut ret = None;
702 let ident = if ret_arrow || cx.peek2(NonReserved, token::OpenParen) {
703 Some(parse_ident(cx)?)
704 } else {
705 None
706 };
707 if cx.peek(token::OpenParen) || cx.peek(token::OpenBrace) {
708 fields = parse_fields(cx)?;
709 if cx.advance_if(token::RArrow) {
710 ret = Some(parse_variant_ret(cx)?);
711 }
712 } else {
713 if ret_arrow {
714 cx.expect(token::RArrow)?;
715 }
716 ret = Some(parse_variant_ret(cx)?);
717 };
718 let hi = cx.hi();
719 Ok(VariantDef { ident, fields, ret, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
720}
721
722fn parse_fields(cx: &mut ParseCtxt) -> ParseResult<Vec<Ty>> {
726 let mut lookahead = cx.lookahead1();
727 if lookahead.peek(token::OpenParen) {
728 parens(cx, Comma, parse_type)
729 } else if lookahead.peek(token::OpenBrace) {
730 braces(cx, Comma, parse_type)
731 } else {
732 Err(lookahead.into_error())
733 }
734}
735
736fn parse_variant_ret(cx: &mut ParseCtxt) -> ParseResult<VariantRet> {
740 let path = parse_path(cx)?;
741 let indices = if cx.peek(token::OpenBracket) {
742 parse_indices(cx)?
743 } else {
744 let hi = cx.hi();
745 Indices { indices: vec![], span: cx.mk_span(hi, hi) }
746 };
747 Ok(VariantRet { path, indices })
748}
749
750pub(crate) fn parse_type_alias(cx: &mut ParseCtxt) -> ParseResult<TyAlias> {
751 let lo = cx.lo();
752 cx.expect(kw::Type)?;
753 let ident = parse_ident(cx)?;
754 let generics = parse_opt_generics(cx)?;
755 let params = if cx.peek(token::OpenParen) {
756 parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?
757 } else {
758 vec![]
759 };
760 let index = if cx.peek(token::OpenBracket) {
761 Some(delimited(cx, Bracket, |cx| parse_refine_param(cx, RequireSort::Yes))?)
762 } else {
763 None
764 };
765 cx.expect(token::Eq)?;
766 let ty = parse_type(cx)?;
767 let hi = cx.hi();
768 Ok(TyAlias {
769 ident,
770 generics,
771 params,
772 index,
773 ty,
774 node_id: cx.next_node_id(),
775 span: cx.mk_span(lo, hi),
776 })
777}
778
779fn parse_opt_generics(cx: &mut ParseCtxt) -> ParseResult<Generics> {
780 if !cx.peek(LAngle) {
781 let hi = cx.hi();
782 return Ok(Generics { params: vec![], predicates: None, span: cx.mk_span(hi, hi) });
783 }
784 let lo = cx.lo();
785 let params = angle(cx, Comma, parse_generic_param)?;
786 let hi = cx.hi();
787 Ok(Generics { params, predicates: None, span: cx.mk_span(lo, hi) })
788}
789
790fn parse_generic_param(cx: &mut ParseCtxt) -> ParseResult<GenericParam> {
791 let name = parse_ident(cx)?;
792 Ok(GenericParam { name, node_id: cx.next_node_id() })
793}
794
795fn invalid_ident_err(ident: &Ident) -> ParseError {
796 ParseError { kind: crate::ParseErrorKind::InvalidBinding, span: ident.span }
797}
798
799fn mut_as_strg(inputs: Vec<FnInput>, ensures: &[Ensures]) -> ParseResult<Vec<FnInput>> {
800 let locs = ensures
802 .iter()
803 .filter_map(|ens| if let Ensures::Type(ident, _, _) = ens { Some(ident) } else { None })
804 .collect::<HashSet<_>>();
805 let mut res = vec![];
807 for input in inputs {
808 if let FnInput::Ty(Some(ident), _, _) = &input
809 && locs.contains(&ident)
810 {
811 let FnInput::Ty(Some(ident), ty, id) = input else {
813 return Err(invalid_ident_err(ident));
814 };
815 let TyKind::Ref(Mutability::Mut, inner_ty) = ty.kind else {
816 return Err(invalid_ident_err(&ident));
817 };
818 res.push(FnInput::StrgRef(ident, *inner_ty, id));
819 } else {
820 res.push(input);
822 }
823 }
824 Ok(res)
825}
826
827pub(crate) fn parse_fn_sig<T: PeekExpected>(cx: &mut ParseCtxt, end: T) -> ParseResult<FnSig> {
835 let lo = cx.lo();
836 let asyncness = parse_asyncness(cx);
837 cx.expect(kw::Fn)?;
838 let ident = if cx.peek(NonReserved) { Some(parse_ident(cx)?) } else { None };
839 let mut generics = parse_opt_generics(cx)?;
840 let params = if cx.peek(token::OpenBracket) {
841 brackets(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?
842 } else {
843 vec![]
844 };
845 let inputs = parens(cx, Comma, parse_fn_input)?;
846 let returns = parse_fn_ret(cx)?;
847 let requires = parse_opt_requires(cx)?;
848 let ensures = parse_opt_ensures(cx)?;
849 let inputs = mut_as_strg(inputs, &ensures)?;
850 generics.predicates = parse_opt_where(cx)?;
851 cx.expect(end)?;
852 let hi = cx.hi();
853 Ok(FnSig {
854 asyncness,
855 generics,
856 params,
857 ident,
858 inputs,
859 requires,
860 output: FnOutput { returns, ensures, node_id: cx.next_node_id() },
861 node_id: cx.next_node_id(),
862 span: cx.mk_span(lo, hi),
863 no_panic: None, })
865}
866
867fn parse_opt_requires(cx: &mut ParseCtxt) -> ParseResult<Vec<Requires>> {
871 if !cx.advance_if(kw::Requires) {
872 return Ok(vec![]);
873 }
874 punctuated_until(
875 cx,
876 Comma,
877 |t: TokenKind| t.is_keyword(kw::Ensures) || t.is_keyword(kw::Where) || t.is_eof(),
878 parse_requires_clause,
879 )
880}
881
882fn parse_requires_clause(cx: &mut ParseCtxt) -> ParseResult<Requires> {
886 let mut params = vec![];
887 if cx.advance_if(kw::Forall) {
888 params = sep1(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
889 cx.expect(token::Dot)?;
890 }
891 let pred = parse_expr(cx, true)?;
892 Ok(Requires { params, pred })
893}
894
895fn parse_opt_ensures(cx: &mut ParseCtxt) -> ParseResult<Vec<Ensures>> {
899 if !cx.advance_if(kw::Ensures) {
900 return Ok(vec![]);
901 }
902 punctuated_until(
903 cx,
904 Comma,
905 |t: TokenKind| t.is_keyword(kw::Where) || t.is_eof(),
906 parse_ensures_clause,
907 )
908}
909
910fn parse_ensures_clause(cx: &mut ParseCtxt) -> ParseResult<Ensures> {
915 if cx.peek2(NonReserved, token::Colon) {
916 let ident = parse_ident(cx)?;
918 cx.expect(token::Colon)?;
919 let ty = parse_type(cx)?;
920 Ok(Ensures::Type(ident, ty, cx.next_node_id()))
921 } else {
922 Ok(Ensures::Pred(parse_expr(cx, true)?))
924 }
925}
926
927fn parse_opt_where(cx: &mut ParseCtxt) -> ParseResult<Option<Vec<WhereBoundPredicate>>> {
928 if !cx.advance_if(kw::Where) {
929 return Ok(None);
930 }
931 Ok(Some(punctuated_until(cx, Comma, token::Eof, parse_where_bound)?))
932}
933
934fn parse_where_bound(cx: &mut ParseCtxt) -> ParseResult<WhereBoundPredicate> {
935 let lo = cx.lo();
936 let bounded_ty = parse_type(cx)?;
937 cx.expect(token::Colon)?;
938 let bounds = parse_generic_bounds(cx)?;
939 let hi = cx.hi();
940 Ok(WhereBoundPredicate { span: cx.mk_span(lo, hi), bounded_ty, bounds })
941}
942
943fn parse_fn_ret(cx: &mut ParseCtxt) -> ParseResult<FnRetTy> {
947 if cx.advance_if(token::RArrow) {
948 Ok(FnRetTy::Ty(Box::new(parse_type(cx)?)))
949 } else {
950 let hi = cx.hi();
951 Ok(FnRetTy::Default(cx.mk_span(hi, hi)))
952 }
953}
954
955fn parse_fn_input(cx: &mut ParseCtxt) -> ParseResult<FnInput> {
962 if cx.peek2(NonReserved, token::Colon) {
963 let bind = parse_ident(cx)?;
964 cx.expect(token::Colon)?;
965 if cx.advance_if2(token::And, kw::Strg) {
966 Ok(FnInput::StrgRef(bind, parse_type(cx)?, cx.next_node_id()))
968 } else if cx.peek(NonReserved) {
969 let path = parse_path(cx)?;
970 if cx.peek3(token::OpenBrace, NonReserved, token::Colon) {
971 let bty = path_to_bty(path);
973 let ty = parse_bty_exists(cx, bty)?;
974 Ok(FnInput::Ty(Some(bind), ty, cx.next_node_id()))
975 } else if cx.peek(token::OpenBrace) {
976 let pred = delimited(cx, Brace, |cx| parse_expr(cx, true))?;
978 Ok(FnInput::Constr(bind, path, pred, cx.next_node_id()))
979 } else {
980 let bty = path_to_bty(path);
982 let ty = parse_bty_rhs(cx, bty)?;
983 Ok(FnInput::Ty(Some(bind), ty, cx.next_node_id()))
984 }
985 } else {
986 Ok(FnInput::Ty(Some(bind), parse_type(cx)?, cx.next_node_id()))
988 }
989 } else {
990 Ok(FnInput::Ty(None, parse_type(cx)?, cx.next_node_id()))
992 }
993}
994
995fn parse_asyncness(cx: &mut ParseCtxt) -> Async {
999 let lo = cx.lo();
1000 if cx.advance_if(kw::Async) {
1001 Async::Yes { node_id: cx.next_node_id(), span: cx.mk_span(lo, cx.hi()) }
1002 } else {
1003 Async::No
1004 }
1005}
1006
1007enum Reft {
1008 Exi(Ident, Expr),
1009 Idx(Indices),
1010 None,
1011}
1012
1013fn parse_reft(cx: &mut ParseCtxt) -> ParseResult<Reft> {
1014 if cx.peek(token::OpenBrace) {
1015 let (bind, pred) = delimited(cx, Brace, |cx| {
1016 let bind = parse_ident(cx)?;
1017 cx.expect(token::Colon)?;
1018 let pred = parse_block_expr(cx)?;
1019 Ok((bind, pred))
1020 })?;
1021 Ok(Reft::Exi(bind, pred))
1022 } else if cx.peek(token::OpenBracket) {
1023 let indices = parse_indices(cx)?;
1024 Ok(Reft::Idx(indices))
1025 } else {
1026 Ok(Reft::None)
1027 }
1028}
1029
1030pub(crate) fn parse_type(cx: &mut ParseCtxt) -> ParseResult<Ty> {
1048 let lo = cx.lo();
1049 let mut lookahead = cx.lookahead1();
1050 let kind = if lookahead.advance_if(kw::Underscore) {
1051 TyKind::Hole
1052 } else if lookahead.advance_if(token::OpenParen) {
1053 let (mut tys, trailing) =
1055 punctuated_with_trailing(cx, Comma, token::CloseParen, parse_type)?;
1056 cx.expect(token::CloseParen)?;
1057 if tys.len() == 1 && !trailing {
1058 return Ok(tys.remove(0));
1059 } else {
1060 TyKind::Tuple(tys)
1061 }
1062 } else if lookahead.peek(token::OpenBrace) {
1063 delimited(cx, Brace, |cx| {
1064 if cx.peek2(NonReserved, AnyOf([token::Comma, token::Dot, token::Colon])) {
1065 parse_general_exists(cx)
1067 } else {
1068 let ty = parse_type(cx)?;
1070 cx.expect(token::Or)?;
1071 let pred = parse_block_expr(cx)?;
1072 Ok(TyKind::Constr(pred, Box::new(ty)))
1073 }
1074 })?
1075 } else if lookahead.advance_if(token::And) {
1076 let mutbl = if cx.advance_if(kw::Mut) { Mutability::Mut } else { Mutability::Not };
1078 TyKind::Ref(mutbl, Box::new(parse_type(cx)?))
1079 } else if lookahead.advance_if(token::Star) {
1080 let mutbl = if cx.advance_if(kw::Mut) {
1082 Mutability::Mut
1083 } else {
1084 cx.expect(kw::Const)?;
1085 Mutability::Not
1086 };
1087 let reft = parse_reft(cx)?;
1089 let inner_ty = parse_type(cx)?;
1090 let bty = BaseTy {
1091 kind: BaseTyKind::Ptr(mutbl, Box::new(inner_ty)),
1092 span: cx.mk_span(lo, cx.hi()),
1093 };
1094 match reft {
1095 Reft::Exi(bind, pred) => TyKind::Exists { bind, bty, pred },
1096 Reft::Idx(indices) => TyKind::Indexed { bty, indices },
1097 Reft::None => TyKind::Base(bty),
1098 }
1099 } else if lookahead.advance_if(token::OpenBracket) {
1100 let ty = parse_type(cx)?;
1101 if cx.advance_if(token::Semi) {
1102 let len = parse_const_arg(cx)?;
1104 cx.expect(token::CloseBracket)?;
1105 TyKind::Array(Box::new(ty), len)
1106 } else {
1107 cx.expect(token::CloseBracket)?;
1109 let span = cx.mk_span(lo, cx.hi());
1110 let kind = BaseTyKind::Slice(Box::new(ty));
1111 return parse_bty_rhs(cx, BaseTy { kind, span });
1112 }
1113 } else if lookahead.advance_if(kw::Impl) {
1114 TyKind::ImplTrait(cx.next_node_id(), parse_generic_bounds(cx)?)
1116 } else if lookahead.peek(NonReserved) {
1117 let path = parse_path(cx)?;
1119 let bty = path_to_bty(path);
1120 return parse_bty_rhs(cx, bty);
1121 } else if lookahead.peek(LAngle) {
1122 let bty = parse_qpath(cx)?;
1124 return parse_bty_rhs(cx, bty);
1125 } else {
1126 return Err(lookahead.into_error());
1127 };
1128 let hi = cx.hi();
1129 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1130}
1131
1132fn parse_qpath(cx: &mut ParseCtxt) -> ParseResult<BaseTy> {
1136 let lo = cx.lo();
1137 cx.expect(LAngle)?;
1138 let qself = parse_type(cx)?;
1139 cx.expect(kw::As)?;
1140 let mut segments = parse_segments(cx)?;
1141 cx.expect(RAngle)?;
1142 cx.expect(token::PathSep)?;
1143 segments.extend(parse_segments(cx)?);
1144 let hi = cx.hi();
1145
1146 let span = cx.mk_span(lo, hi);
1147 let path = Path { segments, refine: vec![], node_id: cx.next_node_id(), span };
1148 let kind = BaseTyKind::Path(Some(Box::new(qself)), path);
1149 Ok(BaseTy { kind, span })
1150}
1151
1152fn parse_general_exists(cx: &mut ParseCtxt) -> ParseResult<TyKind> {
1156 let params = sep1(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
1157 cx.expect(token::Dot)?;
1158 let ty = parse_type(cx)?;
1159 let pred = if cx.advance_if(token::Or) { Some(parse_block_expr(cx)?) } else { None };
1160 Ok(TyKind::GeneralExists { params, ty: Box::new(ty), pred })
1161}
1162
1163fn parse_bty_rhs(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
1169 let lo = bty.span.lo();
1170 if cx.peek(token::OpenBracket) {
1171 let indices = parse_indices(cx)?;
1173 let hi = cx.hi();
1174 let kind = TyKind::Indexed { bty, indices };
1175 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1176 } else if cx.peek(token::OpenBrace) {
1177 parse_bty_exists(cx, bty)
1179 } else {
1180 let hi = cx.hi();
1182 let kind = TyKind::Base(bty);
1183 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1184 }
1185}
1186
1187fn parse_bty_exists(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
1191 let lo = bty.span.lo();
1192 delimited(cx, Brace, |cx| {
1193 let bind = parse_ident(cx)?;
1194 cx.expect(token::Colon)?;
1195 let pred = parse_block_expr(cx)?;
1196 let hi = cx.hi();
1197 let kind = TyKind::Exists { bind, bty, pred };
1198 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1199 })
1200}
1201
1202fn path_to_bty(path: Path) -> BaseTy {
1203 let span = path.span;
1204 BaseTy { kind: BaseTyKind::Path(None, path), span }
1205}
1206
1207fn parse_indices(cx: &mut ParseCtxt) -> ParseResult<Indices> {
1208 let lo = cx.lo();
1209 let indices = brackets(cx, Comma, parse_refine_arg)?;
1210 let hi = cx.hi();
1211 Ok(Indices { indices, span: cx.mk_span(lo, hi) })
1212}
1213
1214fn parse_fn_bound_input(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1215 let lo = cx.lo();
1216 let tys = parens(cx, Comma, parse_type)?;
1217 let hi = cx.hi();
1218 let kind = TyKind::Tuple(tys);
1219 let span = cx.mk_span(lo, hi);
1220 let in_ty = Ty { kind, node_id: cx.next_node_id(), span };
1221 Ok(GenericArg { kind: GenericArgKind::Type(in_ty), node_id: cx.next_node_id() })
1222}
1223
1224fn parse_fn_bound_output(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1225 let lo = cx.lo();
1226
1227 let ty = if cx.advance_if(token::RArrow) {
1228 parse_type(cx)?
1229 } else {
1230 Ty { kind: TyKind::Tuple(vec![]), node_id: cx.next_node_id(), span: cx.mk_span(lo, lo) }
1231 };
1232 let hi = cx.hi();
1233 let ident = Ident { name: Output, span: cx.mk_span(lo, hi) };
1234 Ok(GenericArg { kind: GenericArgKind::Constraint(ident, ty), node_id: cx.next_node_id() })
1235}
1236
1237fn parse_fn_bound_path(cx: &mut ParseCtxt) -> ParseResult<Path> {
1238 let lo = cx.lo();
1239 let ident = parse_ident(cx)?;
1240 let in_arg = parse_fn_bound_input(cx)?;
1241 let out_arg = parse_fn_bound_output(cx)?;
1242 let args = vec![in_arg, out_arg];
1243 let segment = PathSegment { ident, args, node_id: cx.next_node_id() };
1244 let hi = cx.hi();
1245 Ok(Path {
1246 segments: vec![segment],
1247 refine: vec![],
1248 node_id: cx.next_node_id(),
1249 span: cx.mk_span(lo, hi),
1250 })
1251}
1252
1253fn parse_generic_bounds(cx: &mut ParseCtxt) -> ParseResult<GenericBounds> {
1254 let path = if cx.peek(sym::FnOnce) || cx.peek(sym::FnMut) || cx.peek(sym::Fn) {
1255 parse_fn_bound_path(cx)?
1256 } else {
1257 parse_path(cx)?
1258 };
1259 Ok(vec![TraitRef { path, node_id: cx.next_node_id() }])
1260}
1261
1262fn parse_const_arg(cx: &mut ParseCtxt) -> ParseResult<ConstArg> {
1263 let lo = cx.lo();
1264 let mut lookahead = cx.lookahead1();
1265 let kind = if lookahead.peek(AnyLit) {
1266 let len = parse_int(cx)?;
1267 ConstArgKind::Lit(len)
1268 } else if lookahead.peek(NonReserved) {
1269 ConstArgKind::Path(parse_path(cx)?)
1270 } else if lookahead.advance_if(kw::Underscore) {
1271 ConstArgKind::Infer
1272 } else {
1273 return Err(lookahead.into_error());
1274 };
1275 let hi = cx.hi();
1276 Ok(ConstArg { kind, span: cx.mk_span(lo, hi) })
1277}
1278
1279fn parse_path(cx: &mut ParseCtxt) -> ParseResult<Path> {
1283 let lo = cx.lo();
1284 let segments = parse_segments(cx)?;
1285 let refine =
1286 if cx.peek(token::OpenParen) { parens(cx, Comma, parse_refine_arg)? } else { vec![] };
1287 let hi = cx.hi();
1288 Ok(Path { segments, refine, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1289}
1290
1291fn parse_segments(cx: &mut ParseCtxt) -> ParseResult<Vec<PathSegment>> {
1295 sep1(cx, token::PathSep, parse_segment)
1296}
1297
1298fn parse_segment(cx: &mut ParseCtxt) -> ParseResult<PathSegment> {
1302 let ident = parse_ident(cx)?;
1303 let args = opt_angle(cx, Comma, parse_generic_arg)?;
1304 Ok(PathSegment { ident, node_id: cx.next_node_id(), args })
1305}
1306
1307fn parse_generic_arg(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1311 let kind = if cx.peek2(NonReserved, token::Eq) {
1312 let ident = parse_ident(cx)?;
1313 cx.expect(token::Eq)?;
1314 let ty = parse_type(cx)?;
1315 GenericArgKind::Constraint(ident, ty)
1316 } else {
1317 GenericArgKind::Type(parse_type(cx)?)
1318 };
1319 Ok(GenericArg { kind, node_id: cx.next_node_id() })
1320}
1321
1322fn parse_refine_arg(cx: &mut ParseCtxt) -> ParseResult<RefineArg> {
1329 let lo = cx.lo();
1330 let arg = if cx.advance_if(token::At) {
1331 let bind = parse_ident(cx)?;
1333 let hi = cx.hi();
1334 RefineArg::Bind(bind, BindKind::At, cx.mk_span(lo, hi), cx.next_node_id())
1335 } else if cx.peek2(token::Pound, NonReserved) {
1336 cx.expect(token::Pound)?;
1338 let bind = parse_ident(cx)?;
1339 let hi = cx.hi();
1340 RefineArg::Bind(bind, BindKind::Pound, cx.mk_span(lo, hi), cx.next_node_id())
1341 } else if cx.advance_if(Or) {
1342 let params =
1343 punctuated_until(cx, Comma, Or, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
1344 cx.expect(Or)?;
1345 let body = parse_expr(cx, true)?;
1346 let hi = cx.hi();
1347 RefineArg::Abs(params, body, cx.mk_span(lo, hi), cx.next_node_id())
1348 } else {
1349 RefineArg::Expr(parse_expr(cx, true)?)
1351 };
1352 Ok(arg)
1353}
1354
1355enum RequireSort {
1357 Yes,
1359 Maybe,
1361 No,
1363}
1364
1365fn parse_sort_if_required(cx: &mut ParseCtxt, require_sort: RequireSort) -> ParseResult<Sort> {
1366 match require_sort {
1367 RequireSort::No => Ok(Sort::Infer),
1368 RequireSort::Maybe => {
1369 if cx.advance_if(token::Colon) {
1370 parse_sort(cx)
1371 } else {
1372 Ok(Sort::Infer)
1373 }
1374 }
1375 RequireSort::Yes => {
1376 cx.expect(token::Colon)?;
1377 parse_sort(cx)
1378 }
1379 }
1380}
1381
1382fn parse_refine_param(cx: &mut ParseCtxt, require_sort: RequireSort) -> ParseResult<RefineParam> {
1388 let lo = cx.lo();
1389 let mode = parse_opt_param_mode(cx);
1390 let ident = parse_ident(cx)?;
1391 let sort = parse_sort_if_required(cx, require_sort)?;
1392 let hi = cx.hi();
1393 Ok(RefineParam { mode, ident, sort, span: cx.mk_span(lo, hi), node_id: cx.next_node_id() })
1394}
1395
1396fn parse_qualifier_param(cx: &mut ParseCtxt) -> ParseResult<(RefineParam, bool)> {
1403 let is_wildcard = cx.advance_if(token::Pound);
1404 let param = parse_refine_param(cx, RequireSort::Yes)?;
1405 Ok((param, is_wildcard))
1406}
1407
1408fn parse_opt_param_mode(cx: &mut ParseCtxt) -> Option<ParamMode> {
1412 if cx.advance_if(kw::Hrn) {
1413 Some(ParamMode::Horn)
1414 } else if cx.advance_if(kw::Hdl) {
1415 Some(ParamMode::Hindley)
1416 } else {
1417 None
1418 }
1419}
1420
1421pub(crate) fn parse_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1422 parse_binops(cx, Precedence::MIN, allow_struct)
1423}
1424
1425fn parse_binops(cx: &mut ParseCtxt, base: Precedence, allow_struct: bool) -> ParseResult<Expr> {
1426 let mut lhs = unary_expr(cx, allow_struct)?;
1427 loop {
1428 let lo = cx.lo();
1429 let Some((op, ntokens)) = cx.peek_binop() else { break };
1430 let precedence = Precedence::of_binop(&op);
1431 if precedence < base {
1432 break;
1433 }
1434 cx.advance_by(ntokens);
1435 let next = match precedence.associativity() {
1436 Associativity::Right => precedence,
1437 Associativity::Left => precedence.next(),
1438 Associativity::None => {
1439 if let ExprKind::BinaryOp(op, ..) = &lhs.kind
1440 && Precedence::of_binop(op) == precedence
1441 {
1442 return Err(cx.cannot_be_chained(lo, cx.hi()));
1443 }
1444 precedence.next()
1445 }
1446 };
1447 let rhs = parse_binops(cx, next, allow_struct)?;
1448 let span = lhs.span.to(rhs.span);
1449 lhs = Expr {
1450 kind: ExprKind::BinaryOp(op, Box::new([lhs, rhs])),
1451 node_id: cx.next_node_id(),
1452 span,
1453 }
1454 }
1455 Ok(lhs)
1456}
1457
1458fn unary_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1462 let lo = cx.lo();
1463 let kind = if cx.advance_if(token::Minus) {
1464 ExprKind::UnaryOp(UnOp::Neg, Box::new(unary_expr(cx, allow_struct)?))
1465 } else if cx.advance_if(token::Bang) {
1466 ExprKind::UnaryOp(UnOp::Not, Box::new(unary_expr(cx, allow_struct)?))
1467 } else {
1468 return parse_trailer_expr(cx, allow_struct);
1469 };
1470 let hi = cx.hi();
1471 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1472}
1473
1474fn parse_trailer_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1481 let lo = cx.lo();
1482 let mut e = parse_atom(cx, allow_struct)?;
1483 loop {
1484 let kind = if cx.advance_if(token::Dot) {
1485 if let Token { kind: token::Literal(lit), lo, hi } = cx.at(0)
1486 && let Lit { kind: LitKind::Integer, symbol: name, suffix: None, .. } = lit
1487 {
1488 cx.advance();
1490 ExprKind::Dot(Box::new(e), Ident { name, span: cx.mk_span(lo, hi) })
1491 } else {
1492 let field = parse_ident(cx)?;
1494 ExprKind::Dot(Box::new(e), field)
1495 }
1496 } else if cx.peek(token::OpenParen) {
1497 let args = parens(cx, Comma, |cx| parse_expr(cx, true))?;
1499 ExprKind::Call(Box::new(e), args)
1500 } else {
1501 break;
1502 };
1503 let hi = cx.hi();
1504 e = Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) };
1505 }
1506 Ok(e)
1507}
1508
1509fn parse_atom(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1523 let lo = cx.lo();
1524 let mut lookahead = cx.lookahead1();
1525 if lookahead.peek(kw::If) {
1526 parse_if_expr(cx)
1528 } else if lookahead.peek(AnyLit) {
1529 parse_lit(cx)
1531 } else if lookahead.advance_if(token::OpenParen) {
1532 let (mut exprs, trailing) =
1534 punctuated_with_trailing(cx, Comma, token::CloseParen, |cx| parse_expr(cx, true))?;
1535 cx.expect(token::CloseParen)?;
1536 if exprs.len() == 1 && !trailing {
1537 Ok(exprs.remove(0))
1538 } else {
1539 Ok(Expr {
1540 kind: ExprKind::Tuple(exprs),
1541 node_id: cx.next_node_id(),
1542 span: cx.mk_span(lo, cx.hi()),
1543 })
1544 }
1545 } else if lookahead.advance_if(token::Pound) {
1546 let lo = cx.lo();
1548 let exprs = braces(cx, Comma, |cx| parse_expr(cx, true))?;
1549 let hi = cx.hi();
1550 let kind = ExprKind::SetLiteral(exprs);
1551 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1552 } else if lookahead.peek(NonReserved) {
1553 let path = parse_expr_path(cx)?;
1554 let kind = if allow_struct && cx.peek(token::OpenBrace) {
1555 let args = braces(cx, Comma, parse_constructor_arg)?;
1557 ExprKind::Constructor(Some(path), args)
1558 } else {
1559 ExprKind::Path(path)
1561 };
1562 let hi = cx.hi();
1563 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1564 } else if allow_struct && lookahead.peek(token::OpenBrace) {
1565 let args = braces(cx, Comma, parse_constructor_arg)?;
1567 let hi = cx.hi();
1568 Ok(Expr {
1569 kind: ExprKind::Constructor(None, args),
1570 node_id: cx.next_node_id(),
1571 span: cx.mk_span(lo, hi),
1572 })
1573 } else if lookahead.advance_if(LAngle) {
1574 let lo = cx.lo();
1576 let qself = parse_type(cx)?;
1577 cx.expect(kw::As)?;
1578 let path = parse_path(cx)?;
1579 cx.expect(RAngle)?;
1580 cx.expect(token::PathSep)?;
1581 let name = parse_ident(cx)?;
1582 let hi = cx.hi();
1583 let kind = ExprKind::AssocReft(Box::new(qself), path, name);
1584 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1585 } else if lookahead.peek(token::OpenBracket) {
1586 parse_prim_uif(cx)
1587 } else if lookahead.peek(kw::Exists) || lookahead.peek(kw::Forall) {
1588 parse_quantifier(cx)
1589 } else {
1590 Err(lookahead.into_error())
1591 }
1592}
1593
1594fn parse_prim_uif(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1595 let lo = cx.lo();
1596 cx.expect(token::OpenBracket)?;
1597 let op = parse_binop(cx)?;
1598 cx.expect(token::CloseBracket)?;
1599 let hi = cx.hi();
1600 Ok(Expr { kind: ExprKind::PrimUIF(op), node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1601}
1602
1603fn parse_quantifier(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1610 let lo = cx.lo();
1611 let mut lookahead = cx.lookahead1();
1612 let quant = if lookahead.advance_if(kw::Forall) {
1613 QuantKind::Forall
1614 } else if lookahead.advance_if(kw::Exists) {
1615 QuantKind::Exists
1616 } else {
1617 return Err(lookahead.into_error());
1618 };
1619 let param = parse_refine_param(cx, RequireSort::Maybe)?;
1620
1621 let mut lookahead = cx.lookahead1();
1622 let dom = if lookahead.peek(kw::In) {
1623 cx.expect(kw::In)?;
1624 let start = parse_int(cx)?;
1625 cx.expect(token::DotDot)?;
1626 let end = parse_int(cx)?;
1627 Some(start..end)
1628 } else {
1629 None
1630 };
1631 let body = parse_block(cx)?;
1632 let hi = cx.hi();
1633 let kind = ExprKind::Quant(quant, param, dom, Box::new(body));
1634 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1635}
1636
1637fn parse_constructor_arg(cx: &mut ParseCtxt) -> ParseResult<ConstructorArg> {
1641 let lo = cx.lo();
1642 let mut lookahead = cx.lookahead1();
1643 if lookahead.peek(NonReserved) {
1644 let ident = parse_ident(cx)?;
1645 cx.expect(token::Colon)?;
1646 let expr = parse_refine_arg(cx)?;
1647 let hi = cx.hi();
1648 Ok(ConstructorArg::FieldExpr(FieldExpr {
1649 ident,
1650 expr,
1651 node_id: cx.next_node_id(),
1652 span: cx.mk_span(lo, hi),
1653 }))
1654 } else if lookahead.advance_if(token::DotDot) {
1655 let spread = parse_expr(cx, true)?;
1656 let hi = cx.hi();
1657 Ok(ConstructorArg::Spread(Spread {
1658 expr: spread,
1659 node_id: cx.next_node_id(),
1660 span: cx.mk_span(lo, hi),
1661 }))
1662 } else {
1663 Err(lookahead.into_error())
1664 }
1665}
1666
1667fn parse_expr_path(cx: &mut ParseCtxt) -> ParseResult<ExprPath> {
1669 let lo = cx.lo();
1670 let segments = sep1(cx, token::PathSep, parse_expr_path_segment)?;
1671 let hi = cx.hi();
1672 Ok(ExprPath { segments, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1673}
1674
1675fn parse_expr_path_segment(cx: &mut ParseCtxt) -> ParseResult<ExprPathSegment> {
1676 Ok(ExprPathSegment { ident: parse_ident(cx)?, node_id: cx.next_node_id() })
1677}
1678
1679fn parse_if_expr(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1683 let mut branches = vec![];
1684
1685 loop {
1686 let lo = cx.lo();
1687 cx.expect(kw::If)?;
1688 let cond = parse_expr(cx, false)?;
1689 let then_ = parse_block(cx)?;
1690 branches.push((lo, cond, then_));
1691 cx.expect(kw::Else)?;
1692
1693 if !cx.peek(kw::If) {
1694 break;
1695 }
1696 }
1697 let mut else_ = parse_block(cx)?;
1698
1699 let hi = cx.hi();
1700 while let Some((lo, cond, then_)) = branches.pop() {
1701 else_ = Expr {
1702 kind: ExprKind::IfThenElse(Box::new([cond, then_, else_])),
1703 node_id: cx.next_node_id(),
1704 span: cx.mk_span(lo, hi),
1705 };
1706 }
1707 Ok(else_)
1708}
1709
1710fn parse_block(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1712 delimited(cx, Brace, parse_block_expr)
1713}
1714
1715fn parse_block_expr(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1717 let lo = cx.lo();
1718 let decls = repeat_while(cx, kw::Let, parse_let_decl)?;
1719 let body = parse_expr(cx, true)?;
1720 let hi = cx.hi();
1721
1722 if decls.is_empty() {
1723 Ok(body)
1724 } else {
1725 let kind = ExprKind::Block(decls, Box::new(body));
1726 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1727 }
1728}
1729
1730fn parse_let_decl(cx: &mut ParseCtxt) -> ParseResult<LetDecl> {
1732 cx.expect(kw::Let)?;
1733 let param = parse_refine_param(cx, RequireSort::Maybe)?;
1734 cx.expect(token::Eq)?;
1735 let init = parse_expr(cx, true)?;
1736 cx.expect(token::Semi)?;
1737 Ok(LetDecl { param, init })
1738}
1739
1740fn parse_lit(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1744 if let Token { kind: token::Literal(lit), lo, hi } = cx.at(0) {
1745 cx.advance();
1746 Ok(Expr {
1747 kind: ExprKind::Literal(lit),
1748 node_id: cx.next_node_id(),
1749 span: cx.mk_span(lo, hi),
1750 })
1751 } else {
1752 Err(cx.unexpected_token(vec![AnyLit.expected()]))
1753 }
1754}
1755
1756fn parse_ident(cx: &mut ParseCtxt) -> ParseResult<Ident> {
1757 if let Token { kind: token::Ident(name, is_raw), lo, hi } = cx.at(0)
1758 && (!cx.is_reserved(name) || is_raw == IdentIsRaw::Yes)
1759 {
1760 cx.advance();
1761 return Ok(Ident { name, span: cx.mk_span(lo, hi) });
1762 }
1763 Err(cx.unexpected_token(vec![NonReserved.expected()]))
1764}
1765
1766fn parse_int<T: FromStr>(cx: &mut ParseCtxt) -> ParseResult<T> {
1767 if let token::Literal(lit) = cx.at(0).kind
1768 && let Lit { kind: LitKind::Integer, symbol, suffix: None, .. } = lit
1769 && let Ok(value) = symbol.as_str().parse::<T>()
1770 {
1771 cx.advance();
1772 return Ok(value);
1773 }
1774
1775 Err(cx.unexpected_token(vec![Expected::Str(std::any::type_name::<T>())]))
1776}
1777
1778fn parse_sort(cx: &mut ParseCtxt) -> ParseResult<Sort> {
1784 if cx.peek(token::OpenParen) {
1785 let inputs = parens(cx, Comma, parse_base_sort)?;
1787 if cx.advance_if(token::RArrow) {
1788 let output = parse_base_sort(cx)?;
1790 Ok(Sort::Func { inputs, output })
1791 } else {
1792 Ok(Sort::Base(BaseSort::Tuple(inputs)))
1794 }
1795 } else {
1796 let bsort = parse_base_sort(cx)?;
1797 if cx.advance_if(token::RArrow) {
1798 let output = parse_base_sort(cx)?;
1800 Ok(Sort::Func { inputs: vec![bsort], output })
1801 } else {
1802 Ok(Sort::Base(bsort))
1804 }
1805 }
1806}
1807
1808fn parse_base_sort(cx: &mut ParseCtxt) -> ParseResult<BaseSort> {
1816 if cx.advance_if(kw::Bitvec) {
1817 cx.expect(LAngle)?;
1819 let len = parse_int(cx)?;
1820 cx.expect(RAngle)?;
1821 Ok(BaseSort::BitVec(len))
1822 } else if cx.peek(token::OpenParen) {
1823 let sorts = parens(cx, Comma, parse_base_sort)?;
1825 Ok(BaseSort::Tuple(sorts))
1826 } else if cx.advance_if(LAngle) {
1827 let qself = parse_type(cx)?;
1829 cx.expect(kw::As)?;
1830 let mut path = parse_path(cx)?;
1831 cx.expect(RAngle)?;
1832 cx.expect(token::PathSep)?;
1833 path.segments.push(parse_segment(cx)?);
1834 Ok(BaseSort::SortOf(Box::new(qself), path))
1835 } else {
1836 let segments = sep1(cx, token::PathSep, parse_ident)?;
1838 let args = opt_angle(cx, Comma, parse_base_sort)?;
1839 let path = SortPath { segments, args, node_id: cx.next_node_id() };
1840 Ok(BaseSort::Path(path))
1841 }
1842}
1843
1844#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
1846enum Precedence {
1847 Iff,
1849 Implies,
1851 Or,
1853 And,
1855 Compare,
1857 BitOr,
1859 BitXor,
1861 BitAnd,
1863 Shift,
1865 Sum,
1867 Product,
1869 Prefix,
1871}
1872
1873enum Associativity {
1874 Right,
1875 Left,
1876 None,
1877}
1878
1879impl Precedence {
1880 const MIN: Self = Precedence::Iff;
1881
1882 fn of_binop(op: &BinOp) -> Precedence {
1883 match op {
1884 BinOp::Iff => Precedence::Iff,
1885 BinOp::Imp => Precedence::Implies,
1886 BinOp::Or => Precedence::Or,
1887 BinOp::And => Precedence::And,
1888 BinOp::Eq | BinOp::Ne | BinOp::Gt | BinOp::Ge | BinOp::Lt | BinOp::Le => {
1889 Precedence::Compare
1890 }
1891 BinOp::BitOr => Precedence::BitOr,
1892 BinOp::BitXor => Precedence::BitXor,
1893 BinOp::BitAnd => Precedence::BitAnd,
1894 BinOp::BitShl | BinOp::BitShr => Precedence::Shift,
1895 BinOp::Add | BinOp::Sub => Precedence::Sum,
1896 BinOp::Mul | BinOp::Div | BinOp::Mod => Precedence::Product,
1897 }
1898 }
1899
1900 fn next(self) -> Precedence {
1901 match self {
1902 Precedence::Iff => Precedence::Implies,
1903 Precedence::Implies => Precedence::Or,
1904 Precedence::Or => Precedence::And,
1905 Precedence::And => Precedence::Compare,
1906 Precedence::Compare => Precedence::BitOr,
1907 Precedence::BitOr => Precedence::BitXor,
1908 Precedence::BitXor => Precedence::BitAnd,
1909 Precedence::BitAnd => Precedence::Shift,
1910 Precedence::Shift => Precedence::Sum,
1911 Precedence::Sum => Precedence::Product,
1912 Precedence::Product => Precedence::Prefix,
1913 Precedence::Prefix => Precedence::Prefix,
1914 }
1915 }
1916
1917 fn associativity(self) -> Associativity {
1918 match self {
1919 Precedence::Or
1920 | Precedence::And
1921 | Precedence::BitOr
1922 | Precedence::BitXor
1923 | Precedence::BitAnd
1924 | Precedence::Shift
1925 | Precedence::Sum
1926 | Precedence::Product => Associativity::Left,
1927 Precedence::Compare | Precedence::Iff => Associativity::None,
1928 Precedence::Implies | Precedence::Prefix => Associativity::Right,
1929 }
1930 }
1931}