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 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> {
169 let mut lookahead = cx.lookahead1();
170 if lookahead.peek(token::Pound) || lookahead.peek(kw::Fn) {
171 parse_reft_func(cx).map(FluxItem::FuncDef)
172 } else if lookahead.peek(kw::Local)
173 || lookahead.peek(kw::Invariant)
174 || lookahead.peek(kw::Qualifier)
175 {
176 parse_qualifier(cx).map(FluxItem::Qualifier)
177 } else if lookahead.peek(kw::Opaque) {
178 parse_sort_decl(cx).map(FluxItem::SortDecl)
179 } else if lookahead.peek(kw::Property) {
180 parse_primop_property(cx).map(FluxItem::PrimOpProp)
181 } else {
182 Err(lookahead.into_error())
183 }
184}
185
186pub(crate) fn parse_detached_specs(cx: &mut ParseCtxt) -> ParseResult<surface::DetachedSpecs> {
190 let items = until(cx, token::Eof, parse_detached_item)?;
191 Ok(surface::DetachedSpecs { items })
192}
193
194pub(crate) fn parse_detached_item(cx: &mut ParseCtxt) -> ParseResult<DetachedItem> {
202 let attrs = parse_attrs(cx)?;
203 let mut lookahead = cx.lookahead1();
204 if lookahead.peek(kw::Fn) {
205 Ok(parse_detached_fn_sig(cx, attrs)?.map_kind(DetachedItemKind::FnSig))
206 } else if lookahead.peek(kw::Mod) {
207 parse_detached_mod(cx)
208 } else if lookahead.peek(kw::Struct) {
209 parse_detached_struct(cx, attrs)
210 } else if lookahead.peek(kw::Enum) {
211 parse_detached_enum(cx, attrs)
212 } else if lookahead.peek(kw::Impl) {
213 parse_detached_impl(cx, attrs)
214 } else if lookahead.peek(kw::Trait) {
215 parse_detached_trait(cx, attrs)
216 } else if lookahead.peek(kw::Static) {
217 parse_detached_static(cx, attrs)
218 } else {
219 Err(lookahead.into_error())
220 }
221}
222
223fn parse_detached_field(cx: &mut ParseCtxt) -> ParseResult<(Ident, Ty)> {
227 let ident = parse_ident(cx)?;
228 cx.expect(token::Colon)?;
229 let ty = parse_type(cx)?;
230 Ok((ident, ty))
231}
232
233fn parse_detached_enum(cx: &mut ParseCtxt, mut attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
237 cx.expect(kw::Enum)?;
238 let path = parse_expr_path(cx)?;
239 let generics = Some(parse_opt_generics(cx)?);
240 let refined_by = attrs.refined_by();
241 let invariants = attrs.invariant().into_iter().collect();
242 let variants = braces(cx, Comma, |cx| parse_variant(cx, true))?
243 .into_iter()
244 .map(Some)
245 .collect();
246 let enum_def = EnumDef { generics, refined_by, variants, invariants, reflected: false };
247 Ok(DetachedItem {
248 attrs: attrs.normal,
249 path,
250 kind: DetachedItemKind::Enum(enum_def),
251 node_id: cx.next_node_id(),
252 })
253}
254
255fn parse_detached_struct(cx: &mut ParseCtxt, mut attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
256 cx.expect(kw::Struct)?;
257 let path = parse_expr_path(cx)?;
258 let generics = Some(parse_opt_generics(cx)?);
259 let refined_by = attrs.refined_by();
260 let opaque = attrs.is_opaque();
261 let invariants = attrs.invariant().into_iter().collect();
262 let fields = if cx.peek(token::OpenBrace) {
263 braces(cx, Comma, parse_detached_field)?
264 .into_iter()
265 .map(|(_, ty)| Some(ty))
266 .collect()
267 } else if cx.peek(token::OpenParen) {
268 parens(cx, Comma, parse_type)?
269 .into_iter()
270 .map(Some)
271 .collect()
272 } else {
273 cx.expect(token::Semi)?;
274 vec![]
275 };
276 let struct_def = StructDef { generics, opaque, refined_by, invariants, fields };
277 Ok(DetachedItem {
278 attrs: attrs.normal,
279 path,
280 kind: DetachedItemKind::Struct(struct_def),
281 node_id: cx.next_node_id(),
282 })
283}
284
285fn ident_path(cx: &mut ParseCtxt, ident: Ident) -> ExprPath {
286 let span = ident.span;
287 let segments = vec![ExprPathSegment { ident, node_id: cx.next_node_id() }];
288 ExprPath { segments, span, node_id: cx.next_node_id() }
289}
290
291fn parse_detached_fn_sig(
292 cx: &mut ParseCtxt,
293 mut attrs: ParsedAttrs,
294) -> ParseResult<DetachedItem<FnSig>> {
295 let mut fn_sig = parse_fn_sig(cx, token::Semi)?;
296 fn_sig.no_panic = attrs.no_panic_if();
297 let span = fn_sig.span;
298 let ident = fn_sig
299 .ident
300 .ok_or(ParseError { kind: crate::ParseErrorKind::InvalidDetachedSpec, span })?;
301 let path = ident_path(cx, ident);
302 Ok(DetachedItem { attrs: attrs.normal, path, kind: fn_sig, node_id: cx.next_node_id() })
303}
304
305fn parse_detached_static(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
309 cx.expect(kw::Static)?;
310 let path = parse_expr_path(cx)?;
311 cx.expect(token::Colon)?;
312 let ty = parse_type(cx)?;
313 cx.expect(token::Semi)?;
314 Ok(DetachedItem {
315 attrs: attrs.normal,
316 path,
317 kind: DetachedItemKind::Static(StaticInfo { ty }),
318 node_id: cx.next_node_id(),
319 })
320}
321
322fn parse_detached_mod(cx: &mut ParseCtxt) -> ParseResult<DetachedItem> {
326 cx.expect(kw::Mod)?;
327 let path = parse_expr_path(cx)?;
328 cx.expect(TokenKind::open_delim(Brace))?;
329 let items = until(cx, TokenKind::close_delim(Brace), parse_detached_item)?;
330 cx.expect(TokenKind::close_delim(Brace))?;
331 Ok(DetachedItem {
332 attrs: vec![],
333 path,
334 kind: DetachedItemKind::Mod(DetachedSpecs { items }),
335 node_id: cx.next_node_id(),
336 })
337}
338
339fn parse_detached_trait(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
343 cx.expect(kw::Trait)?;
344 let path = parse_expr_path(cx)?;
345 let _generics = parse_opt_generics(cx)?;
346 cx.expect(TokenKind::open_delim(Brace))?;
347
348 let mut items = vec![];
349 let mut refts = vec![];
350 while !cx.peek(TokenKind::close_delim(Brace)) {
351 let assoc_item_attrs = parse_attrs(cx)?;
352 if assoc_item_attrs.is_reft() {
353 refts.push(parse_trait_assoc_reft(cx)?);
354 } else {
355 items.push(parse_detached_fn_sig(cx, assoc_item_attrs)?);
356 }
357 }
358 cx.expect(TokenKind::close_delim(Brace))?;
359 Ok(DetachedItem {
360 attrs: attrs.normal,
361 path,
362 kind: DetachedItemKind::Trait(DetachedTrait { items, refts }),
363 node_id: cx.next_node_id(),
364 })
365}
366
367fn parse_detached_impl(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
371 let lo = cx.lo();
372 cx.expect(kw::Impl)?;
373 let hi = cx.hi();
374 let span = cx.mk_span(lo, hi);
375 let outer_path = parse_expr_path(cx)?;
376 let _generics = parse_opt_generics(cx)?;
377 let inner_path = if cx.advance_if(kw::For) {
378 let path = parse_expr_path(cx)?;
379 let _generics = parse_opt_generics(cx)?;
380 Some(path)
381 } else {
382 None
383 };
384 cx.expect(TokenKind::open_delim(Brace))?;
385
386 let mut items = vec![];
387 let mut refts = vec![];
388 while !cx.peek(TokenKind::close_delim(Brace)) {
389 let assoc_item_attrs = parse_attrs(cx)?;
391 if assoc_item_attrs.is_reft() && inner_path.is_some() {
392 refts.push(parse_impl_assoc_reft(cx)?);
393 } else {
394 items.push(parse_detached_fn_sig(cx, assoc_item_attrs)?);
395 }
396 }
397 cx.expect(TokenKind::close_delim(Brace))?;
398 if let Some(path) = inner_path {
399 Ok(DetachedItem {
400 attrs: attrs.normal,
401 path,
402 kind: DetachedItemKind::TraitImpl(DetachedTraitImpl {
403 trait_: outer_path,
404 items,
405 refts,
406 span,
407 }),
408 node_id: cx.next_node_id(),
409 })
410 } else {
411 Ok(DetachedItem {
412 attrs: attrs.normal,
413 path: outer_path,
414 kind: DetachedItemKind::InherentImpl(DetachedInherentImpl { items, span }),
415 node_id: cx.next_node_id(),
416 })
417 }
418}
419
420fn parse_attr(cx: &mut ParseCtxt, attrs: &mut ParsedAttrs) -> ParseResult {
421 cx.expect(token::Pound)?;
422 cx.expect(token::OpenBracket)?;
423 let mut lookahead = cx.lookahead1();
424 if lookahead.advance_if(kw::Trusted) {
425 if cx.advance_if(token::OpenParen) {
426 parse_reason(cx)?;
427 cx.expect(token::CloseParen)?;
428 }
429 attrs.normal.push(Attr::Trusted(Trusted::Yes));
430 } else if lookahead.advance_if(sym::hide) {
431 attrs.syntax.push(SyntaxAttr::Hide);
432 } else if lookahead.advance_if(kw::Opaque) {
433 attrs.syntax.push(SyntaxAttr::Opaque);
434 } else if lookahead.advance_if(kw::Reft) {
435 attrs.syntax.push(SyntaxAttr::Reft);
436 } else if lookahead.advance_if(kw::RefinedBy) {
437 attrs
438 .syntax
439 .push(SyntaxAttr::RefinedBy(delimited(cx, Parenthesis, parse_refined_by)?));
440 } else if lookahead.advance_if(kw::Invariant) {
441 attrs
442 .syntax
443 .push(SyntaxAttr::Invariant(delimited(cx, Parenthesis, |cx| parse_expr(cx, true))?));
444 } else if lookahead.advance_if(sym::no_panic_if) {
445 attrs
446 .syntax
447 .push(SyntaxAttr::NoPanicIf(parse_expr(cx, true)?));
448 } else {
449 return Err(lookahead.into_error());
450 };
451 cx.expect(token::CloseBracket)
452}
453
454fn parse_attrs(cx: &mut ParseCtxt) -> ParseResult<ParsedAttrs> {
455 let mut attrs = ParsedAttrs::default();
456 repeat_while(cx, token::Pound, |cx| parse_attr(cx, &mut attrs))?;
457 Ok(attrs)
458}
459
460fn parse_reft_func(cx: &mut ParseCtxt) -> ParseResult<SpecFunc> {
468 let attrs = parse_attrs(cx)?;
469 let hide = attrs.is_hide();
470 cx.expect(kw::Fn)?;
471 let name = parse_ident(cx)?;
472 let sort_vars = opt_angle(cx, Comma, parse_ident)?;
473 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
474 cx.expect(token::RArrow)?;
475 let output = parse_sort(cx)?;
476 let body = if cx.peek(token::OpenBrace) {
477 Some(parse_block(cx)?)
478 } else {
479 cx.expect(token::Semi)?;
480 None
481 };
482 Ok(SpecFunc { name, sort_vars, params, output, body, hide })
483}
484
485fn parse_qualifier_kind(cx: &mut ParseCtxt) -> ParseResult<QualifierKind> {
490 let mut lookahead = cx.lookahead1();
491 if lookahead.advance_if(kw::Local) {
492 Ok(QualifierKind::Local)
493 } else if lookahead.advance_if(kw::Invariant) {
494 Ok(QualifierKind::Hint)
495 } else {
496 Ok(QualifierKind::Global)
497 }
498}
499
500fn parse_qualifier(cx: &mut ParseCtxt) -> ParseResult<Qualifier> {
506 let lo = cx.lo();
507 let kind = parse_qualifier_kind(cx)?;
508 cx.expect(kw::Qualifier)?;
509 let mut name = parse_ident(cx)?;
510 let mut params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
511 let expr = parse_block(cx)?;
512 let hi = cx.hi();
513
514 if let QualifierKind::Hint = kind {
515 let mut fvars = expr.free_vars();
516 for param in ¶ms {
517 fvars.remove(¶m.ident);
518 }
519 params.extend(fvars.into_iter().map(|ident| {
520 RefineParam {
521 ident,
522 sort: Sort::Infer,
523 mode: None,
524 span: ident.span,
525 node_id: cx.next_node_id(),
526 }
527 }));
528
529 let span = name.span;
530 let str = format!("{}_{}_{}", name.name.to_ident_string(), span.lo().0, span.hi().0);
531 name = Ident { name: Symbol::intern(&str), ..name };
532 }
533
534 Ok(Qualifier { name, params, expr, span: cx.mk_span(lo, hi), kind })
535}
536
537fn parse_sort_decl(cx: &mut ParseCtxt) -> ParseResult<SortDecl> {
541 cx.expect(kw::Opaque)?;
542 cx.expect(kw::Sort)?;
543 let name = parse_ident(cx)?;
544 let sort_vars = opt_angle(cx, Comma, parse_ident)?;
545 cx.expect(token::Semi)?;
546 Ok(SortDecl { name, sort_vars })
547}
548
549fn parse_binop(cx: &mut ParseCtxt) -> ParseResult<BinOp> {
551 let (op, ntokens) = cx
552 .peek_binop()
553 .ok_or_else(|| cx.unexpected_token(vec![Expected::Str("binary operator")]))?;
554 cx.advance_by(ntokens);
555 Ok(op)
556}
557
558fn parse_primop_property(cx: &mut ParseCtxt) -> ParseResult<PrimOpProp> {
562 let lo = cx.lo();
563 cx.expect(kw::Property)?;
564
565 let name = parse_ident(cx)?;
567
568 cx.expect(token::OpenBracket)?;
570 let op = parse_binop(cx)?;
571 cx.expect(token::CloseBracket)?;
572
573 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::No))?;
575
576 let body = parse_block(cx)?;
577 let hi = cx.hi();
578
579 Ok(PrimOpProp { name, op, params, body, span: cx.mk_span(lo, hi) })
580}
581
582pub(crate) fn parse_trait_assoc_refts(cx: &mut ParseCtxt) -> ParseResult<Vec<TraitAssocReft>> {
583 until(cx, token::Eof, parse_trait_assoc_reft)
584}
585
586fn parse_trait_assoc_reft(cx: &mut ParseCtxt) -> ParseResult<TraitAssocReft> {
592 let lo = cx.lo();
593 let final_ = cx.advance_if(kw::Final);
594 cx.expect(kw::Fn)?;
595 let name = parse_ident(cx)?;
596 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
597 cx.expect(token::RArrow)?;
598 let output = parse_base_sort(cx)?;
599 let body = if cx.peek(token::OpenBrace) {
600 Some(parse_block(cx)?)
601 } else {
602 cx.advance_if(token::Semi);
603 None
604 };
605 let hi = cx.hi();
606 Ok(TraitAssocReft { name, params, output, body, span: cx.mk_span(lo, hi), final_ })
607}
608
609pub(crate) fn parse_impl_assoc_refts(cx: &mut ParseCtxt) -> ParseResult<Vec<ImplAssocReft>> {
610 until(cx, token::Eof, parse_impl_assoc_reft)
611}
612
613fn parse_impl_assoc_reft(cx: &mut ParseCtxt) -> ParseResult<ImplAssocReft> {
617 let lo = cx.lo();
618 cx.expect(kw::Fn)?;
619 let name = parse_ident(cx)?;
620 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
621 cx.expect(token::RArrow)?;
622 let output = parse_base_sort(cx)?;
623 let body = parse_block(cx)?;
624 let hi = cx.hi();
625 Ok(ImplAssocReft { name, params, output, body, span: cx.mk_span(lo, hi) })
626}
627
628pub(crate) fn parse_refined_by(cx: &mut ParseCtxt) -> ParseResult<RefineParams> {
632 punctuated_until(cx, Comma, token::Eof, |cx| parse_refine_param(cx, RequireSort::Yes))
633}
634
635pub(crate) fn parse_variant(cx: &mut ParseCtxt, ret_arrow: bool) -> ParseResult<VariantDef> {
641 let lo = cx.lo();
642 let mut fields = vec![];
643 let mut ret = None;
644 let ident = if ret_arrow || cx.peek2(NonReserved, token::OpenParen) {
645 Some(parse_ident(cx)?)
646 } else {
647 None
648 };
649 if cx.peek(token::OpenParen) || cx.peek(token::OpenBrace) {
650 fields = parse_fields(cx)?;
651 if cx.advance_if(token::RArrow) {
652 ret = Some(parse_variant_ret(cx)?);
653 }
654 } else {
655 if ret_arrow {
656 cx.expect(token::RArrow)?;
657 }
658 ret = Some(parse_variant_ret(cx)?);
659 };
660 let hi = cx.hi();
661 Ok(VariantDef { ident, fields, ret, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
662}
663
664fn parse_fields(cx: &mut ParseCtxt) -> ParseResult<Vec<Ty>> {
668 let mut lookahead = cx.lookahead1();
669 if lookahead.peek(token::OpenParen) {
670 parens(cx, Comma, parse_type)
671 } else if lookahead.peek(token::OpenBrace) {
672 braces(cx, Comma, parse_type)
673 } else {
674 Err(lookahead.into_error())
675 }
676}
677
678fn parse_variant_ret(cx: &mut ParseCtxt) -> ParseResult<VariantRet> {
682 let path = parse_path(cx)?;
683 let indices = if cx.peek(token::OpenBracket) {
684 parse_indices(cx)?
685 } else {
686 let hi = cx.hi();
687 Indices { indices: vec![], span: cx.mk_span(hi, hi) }
688 };
689 Ok(VariantRet { path, indices })
690}
691
692pub(crate) fn parse_type_alias(cx: &mut ParseCtxt) -> ParseResult<TyAlias> {
693 let lo = cx.lo();
694 cx.expect(kw::Type)?;
695 let ident = parse_ident(cx)?;
696 let generics = parse_opt_generics(cx)?;
697 let params = if cx.peek(token::OpenParen) {
698 parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?
699 } else {
700 vec![]
701 };
702 let index = if cx.peek(token::OpenBracket) {
703 Some(delimited(cx, Bracket, |cx| parse_refine_param(cx, RequireSort::Yes))?)
704 } else {
705 None
706 };
707 cx.expect(token::Eq)?;
708 let ty = parse_type(cx)?;
709 let hi = cx.hi();
710 Ok(TyAlias {
711 ident,
712 generics,
713 params,
714 index,
715 ty,
716 node_id: cx.next_node_id(),
717 span: cx.mk_span(lo, hi),
718 })
719}
720
721fn parse_opt_generics(cx: &mut ParseCtxt) -> ParseResult<Generics> {
722 if !cx.peek(LAngle) {
723 let hi = cx.hi();
724 return Ok(Generics { params: vec![], predicates: None, span: cx.mk_span(hi, hi) });
725 }
726 let lo = cx.lo();
727 let params = angle(cx, Comma, parse_generic_param)?;
728 let hi = cx.hi();
729 Ok(Generics { params, predicates: None, span: cx.mk_span(lo, hi) })
730}
731
732fn parse_generic_param(cx: &mut ParseCtxt) -> ParseResult<GenericParam> {
733 let name = parse_ident(cx)?;
734 Ok(GenericParam { name, node_id: cx.next_node_id() })
735}
736
737fn invalid_ident_err(ident: &Ident) -> ParseError {
738 ParseError { kind: crate::ParseErrorKind::InvalidBinding, span: ident.span }
739}
740
741fn mut_as_strg(inputs: Vec<FnInput>, ensures: &[Ensures]) -> ParseResult<Vec<FnInput>> {
742 let locs = ensures
744 .iter()
745 .filter_map(|ens| if let Ensures::Type(ident, _, _) = ens { Some(ident) } else { None })
746 .collect::<HashSet<_>>();
747 let mut res = vec![];
749 for input in inputs {
750 if let FnInput::Ty(Some(ident), _, _) = &input
751 && locs.contains(&ident)
752 {
753 let FnInput::Ty(Some(ident), ty, id) = input else {
755 return Err(invalid_ident_err(ident));
756 };
757 let TyKind::Ref(Mutability::Mut, inner_ty) = ty.kind else {
758 return Err(invalid_ident_err(&ident));
759 };
760 res.push(FnInput::StrgRef(ident, *inner_ty, id));
761 } else {
762 res.push(input);
764 }
765 }
766 Ok(res)
767}
768
769pub(crate) fn parse_fn_sig<T: PeekExpected>(cx: &mut ParseCtxt, end: T) -> ParseResult<FnSig> {
777 let lo = cx.lo();
778 let asyncness = parse_asyncness(cx);
779 cx.expect(kw::Fn)?;
780 let ident = if cx.peek(NonReserved) { Some(parse_ident(cx)?) } else { None };
781 let mut generics = parse_opt_generics(cx)?;
782 let params = if cx.peek(token::OpenBracket) {
783 brackets(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?
784 } else {
785 vec![]
786 };
787 let inputs = parens(cx, Comma, parse_fn_input)?;
788 let returns = parse_fn_ret(cx)?;
789 let requires = parse_opt_requires(cx)?;
790 let ensures = parse_opt_ensures(cx)?;
791 let inputs = mut_as_strg(inputs, &ensures)?;
792 generics.predicates = parse_opt_where(cx)?;
793 cx.expect(end)?;
794 let hi = cx.hi();
795 Ok(FnSig {
796 asyncness,
797 generics,
798 params,
799 ident,
800 inputs,
801 requires,
802 output: FnOutput { returns, ensures, node_id: cx.next_node_id() },
803 node_id: cx.next_node_id(),
804 span: cx.mk_span(lo, hi),
805 no_panic: None, })
807}
808
809fn parse_opt_requires(cx: &mut ParseCtxt) -> ParseResult<Vec<Requires>> {
813 if !cx.advance_if(kw::Requires) {
814 return Ok(vec![]);
815 }
816 punctuated_until(
817 cx,
818 Comma,
819 |t: TokenKind| t.is_keyword(kw::Ensures) || t.is_keyword(kw::Where) || t.is_eof(),
820 parse_requires_clause,
821 )
822}
823
824fn parse_requires_clause(cx: &mut ParseCtxt) -> ParseResult<Requires> {
828 let mut params = vec![];
829 if cx.advance_if(kw::Forall) {
830 params = sep1(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
831 cx.expect(token::Dot)?;
832 }
833 let pred = parse_expr(cx, true)?;
834 Ok(Requires { params, pred })
835}
836
837fn parse_opt_ensures(cx: &mut ParseCtxt) -> ParseResult<Vec<Ensures>> {
841 if !cx.advance_if(kw::Ensures) {
842 return Ok(vec![]);
843 }
844 punctuated_until(
845 cx,
846 Comma,
847 |t: TokenKind| t.is_keyword(kw::Where) || t.is_eof(),
848 parse_ensures_clause,
849 )
850}
851
852fn parse_ensures_clause(cx: &mut ParseCtxt) -> ParseResult<Ensures> {
857 if cx.peek2(NonReserved, token::Colon) {
858 let ident = parse_ident(cx)?;
860 cx.expect(token::Colon)?;
861 let ty = parse_type(cx)?;
862 Ok(Ensures::Type(ident, ty, cx.next_node_id()))
863 } else {
864 Ok(Ensures::Pred(parse_expr(cx, true)?))
866 }
867}
868
869fn parse_opt_where(cx: &mut ParseCtxt) -> ParseResult<Option<Vec<WhereBoundPredicate>>> {
870 if !cx.advance_if(kw::Where) {
871 return Ok(None);
872 }
873 Ok(Some(punctuated_until(cx, Comma, token::Eof, parse_where_bound)?))
874}
875
876fn parse_where_bound(cx: &mut ParseCtxt) -> ParseResult<WhereBoundPredicate> {
877 let lo = cx.lo();
878 let bounded_ty = parse_type(cx)?;
879 cx.expect(token::Colon)?;
880 let bounds = parse_generic_bounds(cx)?;
881 let hi = cx.hi();
882 Ok(WhereBoundPredicate { span: cx.mk_span(lo, hi), bounded_ty, bounds })
883}
884
885fn parse_fn_ret(cx: &mut ParseCtxt) -> ParseResult<FnRetTy> {
889 if cx.advance_if(token::RArrow) {
890 Ok(FnRetTy::Ty(Box::new(parse_type(cx)?)))
891 } else {
892 let hi = cx.hi();
893 Ok(FnRetTy::Default(cx.mk_span(hi, hi)))
894 }
895}
896
897fn parse_fn_input(cx: &mut ParseCtxt) -> ParseResult<FnInput> {
904 if cx.peek2(NonReserved, token::Colon) {
905 let bind = parse_ident(cx)?;
906 cx.expect(token::Colon)?;
907 if cx.advance_if2(token::And, kw::Strg) {
908 Ok(FnInput::StrgRef(bind, parse_type(cx)?, cx.next_node_id()))
910 } else if cx.peek(NonReserved) {
911 let path = parse_path(cx)?;
912 if cx.peek3(token::OpenBrace, NonReserved, token::Colon) {
913 let bty = path_to_bty(path);
915 let ty = parse_bty_exists(cx, bty)?;
916 Ok(FnInput::Ty(Some(bind), ty, cx.next_node_id()))
917 } else if cx.peek(token::OpenBrace) {
918 let pred = delimited(cx, Brace, |cx| parse_expr(cx, true))?;
920 Ok(FnInput::Constr(bind, path, pred, cx.next_node_id()))
921 } else {
922 let bty = path_to_bty(path);
924 let ty = parse_bty_rhs(cx, bty)?;
925 Ok(FnInput::Ty(Some(bind), ty, cx.next_node_id()))
926 }
927 } else {
928 Ok(FnInput::Ty(Some(bind), parse_type(cx)?, cx.next_node_id()))
930 }
931 } else {
932 Ok(FnInput::Ty(None, parse_type(cx)?, cx.next_node_id()))
934 }
935}
936
937fn parse_asyncness(cx: &mut ParseCtxt) -> Async {
941 let lo = cx.lo();
942 if cx.advance_if(kw::Async) {
943 Async::Yes { node_id: cx.next_node_id(), span: cx.mk_span(lo, cx.hi()) }
944 } else {
945 Async::No
946 }
947}
948
949enum Reft {
950 Exi(Ident, Expr),
951 Idx(Indices),
952 None,
953}
954
955fn parse_reft(cx: &mut ParseCtxt) -> ParseResult<Reft> {
956 if cx.peek(token::OpenBrace) {
957 let (bind, pred) = delimited(cx, Brace, |cx| {
958 let bind = parse_ident(cx)?;
959 cx.expect(token::Colon)?;
960 let pred = parse_block_expr(cx)?;
961 Ok((bind, pred))
962 })?;
963 Ok(Reft::Exi(bind, pred))
964 } else if cx.peek(token::OpenBracket) {
965 let indices = parse_indices(cx)?;
966 Ok(Reft::Idx(indices))
967 } else {
968 Ok(Reft::None)
969 }
970}
971
972pub(crate) fn parse_type(cx: &mut ParseCtxt) -> ParseResult<Ty> {
990 let lo = cx.lo();
991 let mut lookahead = cx.lookahead1();
992 let kind = if lookahead.advance_if(kw::Underscore) {
993 TyKind::Hole
994 } else if lookahead.advance_if(token::OpenParen) {
995 let (mut tys, trailing) =
997 punctuated_with_trailing(cx, Comma, token::CloseParen, parse_type)?;
998 cx.expect(token::CloseParen)?;
999 if tys.len() == 1 && !trailing {
1000 return Ok(tys.remove(0));
1001 } else {
1002 TyKind::Tuple(tys)
1003 }
1004 } else if lookahead.peek(token::OpenBrace) {
1005 delimited(cx, Brace, |cx| {
1006 if cx.peek2(NonReserved, AnyOf([token::Comma, token::Dot, token::Colon])) {
1007 parse_general_exists(cx)
1009 } else {
1010 let ty = parse_type(cx)?;
1012 cx.expect(token::Or)?;
1013 let pred = parse_block_expr(cx)?;
1014 Ok(TyKind::Constr(pred, Box::new(ty)))
1015 }
1016 })?
1017 } else if lookahead.advance_if(token::And) {
1018 let mutbl = if cx.advance_if(kw::Mut) { Mutability::Mut } else { Mutability::Not };
1020 TyKind::Ref(mutbl, Box::new(parse_type(cx)?))
1021 } else if lookahead.advance_if(token::Star) {
1022 let mutbl = if cx.advance_if(kw::Mut) {
1024 Mutability::Mut
1025 } else {
1026 cx.expect(kw::Const)?;
1027 Mutability::Not
1028 };
1029 let reft = parse_reft(cx)?;
1031 let inner_ty = parse_type(cx)?;
1032 let bty = BaseTy {
1033 kind: BaseTyKind::Ptr(mutbl, Box::new(inner_ty)),
1034 span: cx.mk_span(lo, cx.hi()),
1035 };
1036 match reft {
1037 Reft::Exi(bind, pred) => TyKind::Exists { bind, bty, pred },
1038 Reft::Idx(indices) => TyKind::Indexed { bty, indices },
1039 Reft::None => TyKind::Base(bty),
1040 }
1041 } else if lookahead.advance_if(token::OpenBracket) {
1042 let ty = parse_type(cx)?;
1043 if cx.advance_if(token::Semi) {
1044 let len = parse_const_arg(cx)?;
1046 cx.expect(token::CloseBracket)?;
1047 TyKind::Array(Box::new(ty), len)
1048 } else {
1049 cx.expect(token::CloseBracket)?;
1051 let span = cx.mk_span(lo, cx.hi());
1052 let kind = BaseTyKind::Slice(Box::new(ty));
1053 return parse_bty_rhs(cx, BaseTy { kind, span });
1054 }
1055 } else if lookahead.advance_if(kw::Impl) {
1056 TyKind::ImplTrait(cx.next_node_id(), parse_generic_bounds(cx)?)
1058 } else if lookahead.peek(NonReserved) {
1059 let path = parse_path(cx)?;
1061 let bty = path_to_bty(path);
1062 return parse_bty_rhs(cx, bty);
1063 } else if lookahead.peek(LAngle) {
1064 let bty = parse_qpath(cx)?;
1066 return parse_bty_rhs(cx, bty);
1067 } else {
1068 return Err(lookahead.into_error());
1069 };
1070 let hi = cx.hi();
1071 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1072}
1073
1074fn parse_qpath(cx: &mut ParseCtxt) -> ParseResult<BaseTy> {
1078 let lo = cx.lo();
1079 cx.expect(LAngle)?;
1080 let qself = parse_type(cx)?;
1081 cx.expect(kw::As)?;
1082 let mut segments = parse_segments(cx)?;
1083 cx.expect(RAngle)?;
1084 cx.expect(token::PathSep)?;
1085 segments.extend(parse_segments(cx)?);
1086 let hi = cx.hi();
1087
1088 let span = cx.mk_span(lo, hi);
1089 let path = Path { segments, refine: vec![], node_id: cx.next_node_id(), span };
1090 let kind = BaseTyKind::Path(Some(Box::new(qself)), path);
1091 Ok(BaseTy { kind, span })
1092}
1093
1094fn parse_general_exists(cx: &mut ParseCtxt) -> ParseResult<TyKind> {
1098 let params = sep1(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
1099 cx.expect(token::Dot)?;
1100 let ty = parse_type(cx)?;
1101 let pred = if cx.advance_if(token::Or) { Some(parse_block_expr(cx)?) } else { None };
1102 Ok(TyKind::GeneralExists { params, ty: Box::new(ty), pred })
1103}
1104
1105fn parse_bty_rhs(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
1111 let lo = bty.span.lo();
1112 if cx.peek(token::OpenBracket) {
1113 let indices = parse_indices(cx)?;
1115 let hi = cx.hi();
1116 let kind = TyKind::Indexed { bty, indices };
1117 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1118 } else if cx.peek(token::OpenBrace) {
1119 parse_bty_exists(cx, bty)
1121 } else {
1122 let hi = cx.hi();
1124 let kind = TyKind::Base(bty);
1125 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1126 }
1127}
1128
1129fn parse_bty_exists(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
1133 let lo = bty.span.lo();
1134 delimited(cx, Brace, |cx| {
1135 let bind = parse_ident(cx)?;
1136 cx.expect(token::Colon)?;
1137 let pred = parse_block_expr(cx)?;
1138 let hi = cx.hi();
1139 let kind = TyKind::Exists { bind, bty, pred };
1140 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1141 })
1142}
1143
1144fn path_to_bty(path: Path) -> BaseTy {
1145 let span = path.span;
1146 BaseTy { kind: BaseTyKind::Path(None, path), span }
1147}
1148
1149fn parse_indices(cx: &mut ParseCtxt) -> ParseResult<Indices> {
1150 let lo = cx.lo();
1151 let indices = brackets(cx, Comma, parse_refine_arg)?;
1152 let hi = cx.hi();
1153 Ok(Indices { indices, span: cx.mk_span(lo, hi) })
1154}
1155
1156fn parse_fn_bound_input(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1157 let lo = cx.lo();
1158 let tys = parens(cx, Comma, parse_type)?;
1159 let hi = cx.hi();
1160 let kind = TyKind::Tuple(tys);
1161 let span = cx.mk_span(lo, hi);
1162 let in_ty = Ty { kind, node_id: cx.next_node_id(), span };
1163 Ok(GenericArg { kind: GenericArgKind::Type(in_ty), node_id: cx.next_node_id() })
1164}
1165
1166fn parse_fn_bound_output(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1167 let lo = cx.lo();
1168
1169 let ty = if cx.advance_if(token::RArrow) {
1170 parse_type(cx)?
1171 } else {
1172 Ty { kind: TyKind::Tuple(vec![]), node_id: cx.next_node_id(), span: cx.mk_span(lo, lo) }
1173 };
1174 let hi = cx.hi();
1175 let ident = Ident { name: Output, span: cx.mk_span(lo, hi) };
1176 Ok(GenericArg { kind: GenericArgKind::Constraint(ident, ty), node_id: cx.next_node_id() })
1177}
1178
1179fn parse_fn_bound_path(cx: &mut ParseCtxt) -> ParseResult<Path> {
1180 let lo = cx.lo();
1181 let ident = parse_ident(cx)?;
1182 let in_arg = parse_fn_bound_input(cx)?;
1183 let out_arg = parse_fn_bound_output(cx)?;
1184 let args = vec![in_arg, out_arg];
1185 let segment = PathSegment { ident, args, node_id: cx.next_node_id() };
1186 let hi = cx.hi();
1187 Ok(Path {
1188 segments: vec![segment],
1189 refine: vec![],
1190 node_id: cx.next_node_id(),
1191 span: cx.mk_span(lo, hi),
1192 })
1193}
1194
1195fn parse_generic_bounds(cx: &mut ParseCtxt) -> ParseResult<GenericBounds> {
1196 let path = if cx.peek(sym::FnOnce) || cx.peek(sym::FnMut) || cx.peek(sym::Fn) {
1197 parse_fn_bound_path(cx)?
1198 } else {
1199 parse_path(cx)?
1200 };
1201 Ok(vec![TraitRef { path, node_id: cx.next_node_id() }])
1202}
1203
1204fn parse_const_arg(cx: &mut ParseCtxt) -> ParseResult<ConstArg> {
1205 let lo = cx.lo();
1206 let mut lookahead = cx.lookahead1();
1207 let kind = if lookahead.peek(AnyLit) {
1208 let len = parse_int(cx)?;
1209 ConstArgKind::Lit(len)
1210 } else if lookahead.advance_if(kw::Underscore) {
1211 ConstArgKind::Infer
1212 } else {
1213 return Err(lookahead.into_error());
1214 };
1215 let hi = cx.hi();
1216 Ok(ConstArg { kind, span: cx.mk_span(lo, hi) })
1217}
1218
1219fn parse_path(cx: &mut ParseCtxt) -> ParseResult<Path> {
1223 let lo = cx.lo();
1224 let segments = parse_segments(cx)?;
1225 let refine =
1226 if cx.peek(token::OpenParen) { parens(cx, Comma, parse_refine_arg)? } else { vec![] };
1227 let hi = cx.hi();
1228 Ok(Path { segments, refine, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1229}
1230
1231fn parse_segments(cx: &mut ParseCtxt) -> ParseResult<Vec<PathSegment>> {
1235 sep1(cx, token::PathSep, parse_segment)
1236}
1237
1238fn parse_segment(cx: &mut ParseCtxt) -> ParseResult<PathSegment> {
1242 let ident = parse_ident(cx)?;
1243 let args = opt_angle(cx, Comma, parse_generic_arg)?;
1244 Ok(PathSegment { ident, node_id: cx.next_node_id(), args })
1245}
1246
1247fn parse_generic_arg(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1251 let kind = if cx.peek2(NonReserved, token::Eq) {
1252 let ident = parse_ident(cx)?;
1253 cx.expect(token::Eq)?;
1254 let ty = parse_type(cx)?;
1255 GenericArgKind::Constraint(ident, ty)
1256 } else {
1257 GenericArgKind::Type(parse_type(cx)?)
1258 };
1259 Ok(GenericArg { kind, node_id: cx.next_node_id() })
1260}
1261
1262fn parse_refine_arg(cx: &mut ParseCtxt) -> ParseResult<RefineArg> {
1269 let lo = cx.lo();
1270 let arg = if cx.advance_if(token::At) {
1271 let bind = parse_ident(cx)?;
1273 let hi = cx.hi();
1274 RefineArg::Bind(bind, BindKind::At, cx.mk_span(lo, hi), cx.next_node_id())
1275 } else if cx.peek2(token::Pound, NonReserved) {
1276 cx.expect(token::Pound)?;
1278 let bind = parse_ident(cx)?;
1279 let hi = cx.hi();
1280 RefineArg::Bind(bind, BindKind::Pound, cx.mk_span(lo, hi), cx.next_node_id())
1281 } else if cx.advance_if(Or) {
1282 let params =
1283 punctuated_until(cx, Comma, Or, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
1284 cx.expect(Or)?;
1285 let body = parse_expr(cx, true)?;
1286 let hi = cx.hi();
1287 RefineArg::Abs(params, body, cx.mk_span(lo, hi), cx.next_node_id())
1288 } else {
1289 RefineArg::Expr(parse_expr(cx, true)?)
1291 };
1292 Ok(arg)
1293}
1294
1295enum RequireSort {
1297 Yes,
1299 Maybe,
1301 No,
1303}
1304
1305fn parse_sort_if_required(cx: &mut ParseCtxt, require_sort: RequireSort) -> ParseResult<Sort> {
1306 match require_sort {
1307 RequireSort::No => Ok(Sort::Infer),
1308 RequireSort::Maybe => {
1309 if cx.advance_if(token::Colon) {
1310 parse_sort(cx)
1311 } else {
1312 Ok(Sort::Infer)
1313 }
1314 }
1315 RequireSort::Yes => {
1316 cx.expect(token::Colon)?;
1317 parse_sort(cx)
1318 }
1319 }
1320}
1321
1322fn parse_refine_param(cx: &mut ParseCtxt, require_sort: RequireSort) -> ParseResult<RefineParam> {
1328 let lo = cx.lo();
1329 let mode = parse_opt_param_mode(cx);
1330 let ident = parse_ident(cx)?;
1331 let sort = parse_sort_if_required(cx, require_sort)?;
1332 let hi = cx.hi();
1333 Ok(RefineParam { mode, ident, sort, span: cx.mk_span(lo, hi), node_id: cx.next_node_id() })
1334}
1335
1336fn parse_opt_param_mode(cx: &mut ParseCtxt) -> Option<ParamMode> {
1340 if cx.advance_if(kw::Hrn) {
1341 Some(ParamMode::Horn)
1342 } else if cx.advance_if(kw::Hdl) {
1343 Some(ParamMode::Hindley)
1344 } else {
1345 None
1346 }
1347}
1348
1349pub(crate) fn parse_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1350 parse_binops(cx, Precedence::MIN, allow_struct)
1351}
1352
1353fn parse_binops(cx: &mut ParseCtxt, base: Precedence, allow_struct: bool) -> ParseResult<Expr> {
1354 let mut lhs = unary_expr(cx, allow_struct)?;
1355 loop {
1356 let lo = cx.lo();
1357 let Some((op, ntokens)) = cx.peek_binop() else { break };
1358 let precedence = Precedence::of_binop(&op);
1359 if precedence < base {
1360 break;
1361 }
1362 cx.advance_by(ntokens);
1363 let next = match precedence.associativity() {
1364 Associativity::Right => precedence,
1365 Associativity::Left => precedence.next(),
1366 Associativity::None => {
1367 if let ExprKind::BinaryOp(op, ..) = &lhs.kind
1368 && Precedence::of_binop(op) == precedence
1369 {
1370 return Err(cx.cannot_be_chained(lo, cx.hi()));
1371 }
1372 precedence.next()
1373 }
1374 };
1375 let rhs = parse_binops(cx, next, allow_struct)?;
1376 let span = lhs.span.to(rhs.span);
1377 lhs = Expr {
1378 kind: ExprKind::BinaryOp(op, Box::new([lhs, rhs])),
1379 node_id: cx.next_node_id(),
1380 span,
1381 }
1382 }
1383 Ok(lhs)
1384}
1385
1386fn unary_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1390 let lo = cx.lo();
1391 let kind = if cx.advance_if(token::Minus) {
1392 ExprKind::UnaryOp(UnOp::Neg, Box::new(unary_expr(cx, allow_struct)?))
1393 } else if cx.advance_if(token::Bang) {
1394 ExprKind::UnaryOp(UnOp::Not, Box::new(unary_expr(cx, allow_struct)?))
1395 } else {
1396 return parse_trailer_expr(cx, allow_struct);
1397 };
1398 let hi = cx.hi();
1399 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1400}
1401
1402fn parse_trailer_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1409 let lo = cx.lo();
1410 let mut e = parse_atom(cx, allow_struct)?;
1411 loop {
1412 let kind = if cx.advance_if(token::Dot) {
1413 if let Token { kind: token::Literal(lit), lo, hi } = cx.at(0)
1414 && let Lit { kind: LitKind::Integer, symbol: name, suffix: None, .. } = lit
1415 {
1416 cx.advance();
1418 ExprKind::Dot(Box::new(e), Ident { name, span: cx.mk_span(lo, hi) })
1419 } else {
1420 let field = parse_ident(cx)?;
1422 ExprKind::Dot(Box::new(e), field)
1423 }
1424 } else if cx.peek(token::OpenParen) {
1425 let args = parens(cx, Comma, |cx| parse_expr(cx, true))?;
1427 ExprKind::Call(Box::new(e), args)
1428 } else {
1429 break;
1430 };
1431 let hi = cx.hi();
1432 e = Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) };
1433 }
1434 Ok(e)
1435}
1436
1437fn parse_atom(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1451 let lo = cx.lo();
1452 let mut lookahead = cx.lookahead1();
1453 if lookahead.peek(kw::If) {
1454 parse_if_expr(cx)
1456 } else if lookahead.peek(AnyLit) {
1457 parse_lit(cx)
1459 } else if lookahead.advance_if(token::OpenParen) {
1460 let (mut exprs, trailing) =
1462 punctuated_with_trailing(cx, Comma, token::CloseParen, |cx| parse_expr(cx, true))?;
1463 cx.expect(token::CloseParen)?;
1464 if exprs.len() == 1 && !trailing {
1465 Ok(exprs.remove(0))
1466 } else {
1467 Ok(Expr {
1468 kind: ExprKind::Tuple(exprs),
1469 node_id: cx.next_node_id(),
1470 span: cx.mk_span(lo, cx.hi()),
1471 })
1472 }
1473 } else if lookahead.advance_if(token::Pound) {
1474 let lo = cx.lo();
1476 let exprs = braces(cx, Comma, |cx| parse_expr(cx, true))?;
1477 let hi = cx.hi();
1478 let kind = ExprKind::SetLiteral(exprs);
1479 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1480 } else if lookahead.peek(NonReserved) {
1481 let path = parse_expr_path(cx)?;
1482 let kind = if allow_struct && cx.peek(token::OpenBrace) {
1483 let args = braces(cx, Comma, parse_constructor_arg)?;
1485 ExprKind::Constructor(Some(path), args)
1486 } else {
1487 ExprKind::Path(path)
1489 };
1490 let hi = cx.hi();
1491 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1492 } else if allow_struct && lookahead.peek(token::OpenBrace) {
1493 let args = braces(cx, Comma, parse_constructor_arg)?;
1495 let hi = cx.hi();
1496 Ok(Expr {
1497 kind: ExprKind::Constructor(None, args),
1498 node_id: cx.next_node_id(),
1499 span: cx.mk_span(lo, hi),
1500 })
1501 } else if lookahead.advance_if(LAngle) {
1502 let lo = cx.lo();
1504 let qself = parse_type(cx)?;
1505 cx.expect(kw::As)?;
1506 let path = parse_path(cx)?;
1507 cx.expect(RAngle)?;
1508 cx.expect(token::PathSep)?;
1509 let name = parse_ident(cx)?;
1510 let hi = cx.hi();
1511 let kind = ExprKind::AssocReft(Box::new(qself), path, name);
1512 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1513 } else if lookahead.peek(token::OpenBracket) {
1514 parse_prim_uif(cx)
1515 } else if lookahead.peek(kw::Exists) || lookahead.peek(kw::Forall) {
1516 parse_bounded_quantifier(cx)
1517 } else {
1518 Err(lookahead.into_error())
1519 }
1520}
1521
1522fn parse_prim_uif(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1523 let lo = cx.lo();
1524 cx.expect(token::OpenBracket)?;
1525 let op = parse_binop(cx)?;
1526 cx.expect(token::CloseBracket)?;
1527 let hi = cx.hi();
1528 Ok(Expr { kind: ExprKind::PrimUIF(op), node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1529}
1530
1531fn parse_bounded_quantifier(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1536 let lo = cx.lo();
1537 let mut lookahead = cx.lookahead1();
1538 let quant = if lookahead.advance_if(kw::Forall) {
1539 QuantKind::Forall
1540 } else if lookahead.advance_if(kw::Exists) {
1541 QuantKind::Exists
1542 } else {
1543 return Err(lookahead.into_error());
1544 };
1545 let param = parse_refine_param(cx, RequireSort::Maybe)?;
1546 cx.expect(kw::In)?;
1547 let start = parse_int(cx)?;
1548 cx.expect(token::DotDot)?;
1549 let end = parse_int(cx)?;
1550 let body = parse_block(cx)?;
1551 let hi = cx.hi();
1552 Ok(Expr {
1553 kind: ExprKind::BoundedQuant(quant, param, start..end, Box::new(body)),
1554 node_id: cx.next_node_id(),
1555 span: cx.mk_span(lo, hi),
1556 })
1557}
1558
1559fn parse_constructor_arg(cx: &mut ParseCtxt) -> ParseResult<ConstructorArg> {
1563 let lo = cx.lo();
1564 let mut lookahead = cx.lookahead1();
1565 if lookahead.peek(NonReserved) {
1566 let ident = parse_ident(cx)?;
1567 cx.expect(token::Colon)?;
1568 let expr = parse_expr(cx, true)?;
1569 let hi = cx.hi();
1570 Ok(ConstructorArg::FieldExpr(FieldExpr {
1571 ident,
1572 expr,
1573 node_id: cx.next_node_id(),
1574 span: cx.mk_span(lo, hi),
1575 }))
1576 } else if lookahead.advance_if(token::DotDot) {
1577 let spread = parse_expr(cx, true)?;
1578 let hi = cx.hi();
1579 Ok(ConstructorArg::Spread(Spread {
1580 expr: spread,
1581 node_id: cx.next_node_id(),
1582 span: cx.mk_span(lo, hi),
1583 }))
1584 } else {
1585 Err(lookahead.into_error())
1586 }
1587}
1588
1589fn parse_expr_path(cx: &mut ParseCtxt) -> ParseResult<ExprPath> {
1591 let lo = cx.lo();
1592 let segments = sep1(cx, token::PathSep, parse_expr_path_segment)?;
1593 let hi = cx.hi();
1594 Ok(ExprPath { segments, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1595}
1596
1597fn parse_expr_path_segment(cx: &mut ParseCtxt) -> ParseResult<ExprPathSegment> {
1598 Ok(ExprPathSegment { ident: parse_ident(cx)?, node_id: cx.next_node_id() })
1599}
1600
1601fn parse_if_expr(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1605 let mut branches = vec![];
1606
1607 loop {
1608 let lo = cx.lo();
1609 cx.expect(kw::If)?;
1610 let cond = parse_expr(cx, false)?;
1611 let then_ = parse_block(cx)?;
1612 branches.push((lo, cond, then_));
1613 cx.expect(kw::Else)?;
1614
1615 if !cx.peek(kw::If) {
1616 break;
1617 }
1618 }
1619 let mut else_ = parse_block(cx)?;
1620
1621 let hi = cx.hi();
1622 while let Some((lo, cond, then_)) = branches.pop() {
1623 else_ = Expr {
1624 kind: ExprKind::IfThenElse(Box::new([cond, then_, else_])),
1625 node_id: cx.next_node_id(),
1626 span: cx.mk_span(lo, hi),
1627 };
1628 }
1629 Ok(else_)
1630}
1631
1632fn parse_block(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1634 delimited(cx, Brace, parse_block_expr)
1635}
1636
1637fn parse_block_expr(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1639 let lo = cx.lo();
1640 let decls = repeat_while(cx, kw::Let, parse_let_decl)?;
1641 let body = parse_expr(cx, true)?;
1642 let hi = cx.hi();
1643
1644 if decls.is_empty() {
1645 Ok(body)
1646 } else {
1647 let kind = ExprKind::Block(decls, Box::new(body));
1648 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1649 }
1650}
1651
1652fn parse_let_decl(cx: &mut ParseCtxt) -> ParseResult<LetDecl> {
1654 cx.expect(kw::Let)?;
1655 let param = parse_refine_param(cx, RequireSort::Maybe)?;
1656 cx.expect(token::Eq)?;
1657 let init = parse_expr(cx, true)?;
1658 cx.expect(token::Semi)?;
1659 Ok(LetDecl { param, init })
1660}
1661
1662fn parse_lit(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1666 if let Token { kind: token::Literal(lit), lo, hi } = cx.at(0) {
1667 cx.advance();
1668 Ok(Expr {
1669 kind: ExprKind::Literal(lit),
1670 node_id: cx.next_node_id(),
1671 span: cx.mk_span(lo, hi),
1672 })
1673 } else {
1674 Err(cx.unexpected_token(vec![AnyLit.expected()]))
1675 }
1676}
1677
1678fn parse_ident(cx: &mut ParseCtxt) -> ParseResult<Ident> {
1679 if let Token { kind: token::Ident(name, is_raw), lo, hi } = cx.at(0)
1680 && (!cx.is_reserved(name) || is_raw == IdentIsRaw::Yes)
1681 {
1682 cx.advance();
1683 return Ok(Ident { name, span: cx.mk_span(lo, hi) });
1684 }
1685 Err(cx.unexpected_token(vec![NonReserved.expected()]))
1686}
1687
1688fn parse_int<T: FromStr>(cx: &mut ParseCtxt) -> ParseResult<T> {
1689 if let token::Literal(lit) = cx.at(0).kind
1690 && let Lit { kind: LitKind::Integer, symbol, suffix: None, .. } = lit
1691 && let Ok(value) = symbol.as_str().parse::<T>()
1692 {
1693 cx.advance();
1694 return Ok(value);
1695 }
1696
1697 Err(cx.unexpected_token(vec![Expected::Str(std::any::type_name::<T>())]))
1698}
1699
1700fn parse_sort(cx: &mut ParseCtxt) -> ParseResult<Sort> {
1706 if cx.peek(token::OpenParen) {
1707 let inputs = parens(cx, Comma, parse_base_sort)?;
1709 if cx.advance_if(token::RArrow) {
1710 let output = parse_base_sort(cx)?;
1712 Ok(Sort::Func { inputs, output })
1713 } else {
1714 Ok(Sort::Base(BaseSort::Tuple(inputs)))
1716 }
1717 } else {
1718 let bsort = parse_base_sort(cx)?;
1719 if cx.advance_if(token::RArrow) {
1720 let output = parse_base_sort(cx)?;
1722 Ok(Sort::Func { inputs: vec![bsort], output })
1723 } else {
1724 Ok(Sort::Base(bsort))
1726 }
1727 }
1728}
1729
1730fn parse_base_sort(cx: &mut ParseCtxt) -> ParseResult<BaseSort> {
1738 if cx.advance_if(kw::Bitvec) {
1739 cx.expect(LAngle)?;
1741 let len = parse_int(cx)?;
1742 cx.expect(RAngle)?;
1743 Ok(BaseSort::BitVec(len))
1744 } else if cx.peek(token::OpenParen) {
1745 let sorts = parens(cx, Comma, parse_base_sort)?;
1747 Ok(BaseSort::Tuple(sorts))
1748 } else if cx.advance_if(LAngle) {
1749 let qself = parse_type(cx)?;
1751 cx.expect(kw::As)?;
1752 let mut path = parse_path(cx)?;
1753 cx.expect(RAngle)?;
1754 cx.expect(token::PathSep)?;
1755 path.segments.push(parse_segment(cx)?);
1756 Ok(BaseSort::SortOf(Box::new(qself), path))
1757 } else {
1758 let segments = sep1(cx, token::PathSep, parse_ident)?;
1760 let args = opt_angle(cx, Comma, parse_base_sort)?;
1761 let path = SortPath { segments, args, node_id: cx.next_node_id() };
1762 Ok(BaseSort::Path(path))
1763 }
1764}
1765
1766#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
1768enum Precedence {
1769 Iff,
1771 Implies,
1773 Or,
1775 And,
1777 Compare,
1779 BitOr,
1781 BitXor,
1783 BitAnd,
1785 Shift,
1787 Sum,
1789 Product,
1791 Prefix,
1793}
1794
1795enum Associativity {
1796 Right,
1797 Left,
1798 None,
1799}
1800
1801impl Precedence {
1802 const MIN: Self = Precedence::Iff;
1803
1804 fn of_binop(op: &BinOp) -> Precedence {
1805 match op {
1806 BinOp::Iff => Precedence::Iff,
1807 BinOp::Imp => Precedence::Implies,
1808 BinOp::Or => Precedence::Or,
1809 BinOp::And => Precedence::And,
1810 BinOp::Eq | BinOp::Ne | BinOp::Gt | BinOp::Ge | BinOp::Lt | BinOp::Le => {
1811 Precedence::Compare
1812 }
1813 BinOp::BitOr => Precedence::BitOr,
1814 BinOp::BitXor => Precedence::BitXor,
1815 BinOp::BitAnd => Precedence::BitAnd,
1816 BinOp::BitShl | BinOp::BitShr => Precedence::Shift,
1817 BinOp::Add | BinOp::Sub => Precedence::Sum,
1818 BinOp::Mul | BinOp::Div | BinOp::Mod => Precedence::Product,
1819 }
1820 }
1821
1822 fn next(self) -> Precedence {
1823 match self {
1824 Precedence::Iff => Precedence::Implies,
1825 Precedence::Implies => Precedence::Or,
1826 Precedence::Or => Precedence::And,
1827 Precedence::And => Precedence::Compare,
1828 Precedence::Compare => Precedence::BitOr,
1829 Precedence::BitOr => Precedence::BitXor,
1830 Precedence::BitXor => Precedence::BitAnd,
1831 Precedence::BitAnd => Precedence::Shift,
1832 Precedence::Shift => Precedence::Sum,
1833 Precedence::Sum => Precedence::Product,
1834 Precedence::Product => Precedence::Prefix,
1835 Precedence::Prefix => Precedence::Prefix,
1836 }
1837 }
1838
1839 fn associativity(self) -> Associativity {
1840 match self {
1841 Precedence::Or
1842 | Precedence::And
1843 | Precedence::BitOr
1844 | Precedence::BitXor
1845 | Precedence::BitAnd
1846 | Precedence::Shift
1847 | Precedence::Sum
1848 | Precedence::Product => Associativity::Left,
1849 Precedence::Compare | Precedence::Iff => Associativity::None,
1850 Precedence::Implies | Precedence::Prefix => Associativity::Right,
1851 }
1852 }
1853}