1pub(crate) mod lookahead;
2mod utils;
3use std::{collections::HashSet, str::FromStr, vec};
4
5use lookahead::{AnyLit, LAngle, NonReserved, RAngle};
6use rustc_span::{Symbol, sym::Output};
7use utils::{
8 angle, braces, brackets, delimited, opt_angle, parens, punctuated_until,
9 punctuated_with_trailing, repeat_while, sep1, until,
10};
11
12use crate::{
13 ParseCtxt, ParseError, ParseResult,
14 parser::lookahead::{AnyOf, Expected, PeekExpected},
15 surface::{
16 self, Async,
17 Attr::{self},
18 BaseSort, BaseTy, BaseTyKind, BinOp, BindKind, ConstArg, ConstArgKind, ConstructorArg,
19 DetachedInherentImpl, DetachedItem, DetachedItemKind, DetachedSpecs, DetachedTrait,
20 DetachedTraitImpl, Ensures, EnumDef, Expr, ExprKind, ExprPath, ExprPathSegment, FieldExpr,
21 FluxItem, FnInput, FnOutput, FnRetTy, FnSig, GenericArg, GenericArgKind, GenericBounds,
22 GenericParam, Generics, Ident, ImplAssocReft, Indices, LetDecl, LitKind, Mutability,
23 ParamMode, Path, PathSegment, PrimOpProp, Qualifier, QualifierKind, QuantKind, RefineArg,
24 RefineParam, RefineParams, Requires, Sort, SortDecl, SortPath, SpecFunc, Spread, StructDef,
25 TraitAssocReft, TraitRef, Trusted, Ty, TyAlias, TyKind, UnOp, VariantDef, VariantRet,
26 WhereBoundPredicate,
27 },
28 symbols::{kw, sym},
29 token::{self, Comma, Delimiter::*, IdentIsRaw, Or, Token, TokenKind},
30};
31
32enum SyntaxAttr {
40 Reft,
42 Invariant(Expr),
44 RefinedBy(RefineParams),
46 Hide,
53 Opaque,
55}
56
57#[derive(Default)]
58struct ParsedAttrs {
59 normal: Vec<Attr>,
60 syntax: Vec<SyntaxAttr>,
61}
62
63impl ParsedAttrs {
64 fn is_reft(&self) -> bool {
65 self.syntax
66 .iter()
67 .any(|attr| matches!(attr, SyntaxAttr::Reft))
68 }
69
70 fn is_hide(&self) -> bool {
71 self.syntax
72 .iter()
73 .any(|attr| matches!(attr, SyntaxAttr::Hide))
74 }
75
76 fn is_opaque(&self) -> bool {
77 self.syntax
78 .iter()
79 .any(|attr| matches!(attr, SyntaxAttr::Opaque))
80 }
81
82 fn refined_by(&mut self) -> Option<RefineParams> {
83 let pos = self
84 .syntax
85 .iter()
86 .position(|x| matches!(x, SyntaxAttr::RefinedBy(_)))?;
87 if let SyntaxAttr::RefinedBy(params) = self.syntax.remove(pos) {
88 Some(params)
89 } else {
90 None
91 }
92 }
93
94 fn invariant(&mut self) -> Option<Expr> {
95 let pos = self
96 .syntax
97 .iter()
98 .position(|x| matches!(x, SyntaxAttr::Invariant(_)))?;
99 if let SyntaxAttr::Invariant(exp) = self.syntax.remove(pos) { Some(exp) } else { None }
100 }
101}
102
103pub(crate) fn parse_yes_or_no_with_reason(cx: &mut ParseCtxt) -> ParseResult<bool> {
109 let mut lookahead = cx.lookahead1();
110 if lookahead.advance_if(sym::yes) {
111 if cx.advance_if(token::Comma) {
112 parse_reason(cx)?;
113 }
114 Ok(true)
115 } else if lookahead.advance_if(sym::no) {
116 if cx.advance_if(token::Comma) {
117 parse_reason(cx)?;
118 }
119 Ok(false)
120 } else if lookahead.peek(sym::reason) {
121 parse_reason(cx)?;
122 Ok(true)
123 } else {
124 Err(lookahead.into_error())
125 }
126}
127
128fn parse_reason(cx: &mut ParseCtxt) -> ParseResult {
132 cx.expect(sym::reason)?;
133 cx.expect(token::Eq)?;
134 cx.expect(AnyLit)
135}
136
137pub(crate) fn parse_ident_list(cx: &mut ParseCtxt) -> ParseResult<Vec<Ident>> {
141 punctuated_until(cx, Comma, token::Eof, parse_ident)
142}
143
144pub(crate) fn parse_flux_items(cx: &mut ParseCtxt) -> ParseResult<Vec<FluxItem>> {
148 until(cx, token::Eof, parse_flux_item)
149}
150
151fn parse_flux_item(cx: &mut ParseCtxt) -> ParseResult<FluxItem> {
158 let mut lookahead = cx.lookahead1();
159 if lookahead.peek(token::Pound) || lookahead.peek(kw::Fn) {
160 parse_reft_func(cx).map(FluxItem::FuncDef)
161 } else if lookahead.peek(kw::Local)
162 || lookahead.peek(kw::Invariant)
163 || lookahead.peek(kw::Qualifier)
164 {
165 parse_qualifier(cx).map(FluxItem::Qualifier)
166 } else if lookahead.peek(kw::Opaque) {
167 parse_sort_decl(cx).map(FluxItem::SortDecl)
168 } else if lookahead.peek(kw::Property) {
169 parse_primop_property(cx).map(FluxItem::PrimOpProp)
170 } else {
171 Err(lookahead.into_error())
172 }
173}
174
175pub(crate) fn parse_detached_specs(cx: &mut ParseCtxt) -> ParseResult<surface::DetachedSpecs> {
179 let items = until(cx, token::Eof, parse_detached_item)?;
180 Ok(surface::DetachedSpecs { items })
181}
182
183pub(crate) fn parse_detached_item(cx: &mut ParseCtxt) -> ParseResult<DetachedItem> {
191 let attrs = parse_attrs(cx)?;
192 let mut lookahead = cx.lookahead1();
193 if lookahead.peek(kw::Fn) {
194 Ok(parse_detached_fn_sig(cx, attrs)?.map_kind(DetachedItemKind::FnSig))
195 } else if lookahead.peek(kw::Mod) {
196 parse_detached_mod(cx)
197 } else if lookahead.peek(kw::Struct) {
198 parse_detached_struct(cx, attrs)
199 } else if lookahead.peek(kw::Enum) {
200 parse_detached_enum(cx, attrs)
201 } else if lookahead.peek(kw::Impl) {
202 parse_detached_impl(cx, attrs)
203 } else if lookahead.peek(kw::Trait) {
204 parse_detached_trait(cx, attrs)
205 } else {
206 Err(lookahead.into_error())
207 }
208}
209
210fn parse_detached_field(cx: &mut ParseCtxt) -> ParseResult<(Ident, Ty)> {
214 let ident = parse_ident(cx)?;
215 cx.expect(token::Colon)?;
216 let ty = parse_type(cx)?;
217 Ok((ident, ty))
218}
219
220fn parse_detached_enum(cx: &mut ParseCtxt, mut attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
224 cx.expect(kw::Enum)?;
225 let path = parse_expr_path(cx)?;
226 let generics = Some(parse_opt_generics(cx)?);
227 let refined_by = attrs.refined_by();
228 let invariants = attrs.invariant().into_iter().collect();
229 let variants = braces(cx, Comma, |cx| parse_variant(cx, true))?
230 .into_iter()
231 .map(Some)
232 .collect();
233 let enum_def = EnumDef { generics, refined_by, variants, invariants, reflected: false };
234 Ok(DetachedItem {
235 attrs: attrs.normal,
236 path,
237 kind: DetachedItemKind::Enum(enum_def),
238 node_id: cx.next_node_id(),
239 })
240}
241
242fn parse_detached_struct(cx: &mut ParseCtxt, mut attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
243 cx.expect(kw::Struct)?;
244 let path = parse_expr_path(cx)?;
245 let generics = Some(parse_opt_generics(cx)?);
246 let refined_by = attrs.refined_by();
247 let opaque = attrs.is_opaque();
248 let invariants = attrs.invariant().into_iter().collect();
249 let fields = if cx.peek(token::OpenBrace) {
250 braces(cx, Comma, parse_detached_field)?
251 .into_iter()
252 .map(|(_, ty)| Some(ty))
253 .collect()
254 } else if cx.peek(token::OpenParen) {
255 parens(cx, Comma, parse_type)?
256 .into_iter()
257 .map(Some)
258 .collect()
259 } else {
260 cx.expect(token::Semi)?;
261 vec![]
262 };
263 let struct_def = StructDef { generics, opaque, refined_by, invariants, fields };
264 Ok(DetachedItem {
265 attrs: attrs.normal,
266 path,
267 kind: DetachedItemKind::Struct(struct_def),
268 node_id: cx.next_node_id(),
269 })
270}
271
272fn ident_path(cx: &mut ParseCtxt, ident: Ident) -> ExprPath {
273 let span = ident.span;
274 let segments = vec![ExprPathSegment { ident, node_id: cx.next_node_id() }];
275 ExprPath { segments, span, node_id: cx.next_node_id() }
276}
277
278fn parse_detached_fn_sig(
279 cx: &mut ParseCtxt,
280 attrs: ParsedAttrs,
281) -> ParseResult<DetachedItem<FnSig>> {
282 let fn_sig = parse_fn_sig(cx, token::Semi)?;
283 let span = fn_sig.span;
284 let ident = fn_sig
285 .ident
286 .ok_or(ParseError { kind: crate::ParseErrorKind::InvalidDetachedSpec, span })?;
287 let path = ident_path(cx, ident);
288 Ok(DetachedItem { attrs: attrs.normal, path, kind: fn_sig, node_id: cx.next_node_id() })
289}
290
291fn parse_detached_mod(cx: &mut ParseCtxt) -> ParseResult<DetachedItem> {
295 cx.expect(kw::Mod)?;
296 let path = parse_expr_path(cx)?;
297 cx.expect(TokenKind::open_delim(Brace))?;
298 let items = until(cx, TokenKind::close_delim(Brace), parse_detached_item)?;
299 cx.expect(TokenKind::close_delim(Brace))?;
300 Ok(DetachedItem {
301 attrs: vec![],
302 path,
303 kind: DetachedItemKind::Mod(DetachedSpecs { items }),
304 node_id: cx.next_node_id(),
305 })
306}
307
308fn parse_detached_trait(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
312 cx.expect(kw::Trait)?;
313 let path = parse_expr_path(cx)?;
314 let _generics = parse_opt_generics(cx)?;
315 cx.expect(TokenKind::open_delim(Brace))?;
316
317 let mut items = vec![];
318 let mut refts = vec![];
319 while !cx.peek(TokenKind::close_delim(Brace)) {
320 let assoc_item_attrs = parse_attrs(cx)?;
321 if assoc_item_attrs.is_reft() {
322 refts.push(parse_trait_assoc_reft(cx)?);
323 } else {
324 items.push(parse_detached_fn_sig(cx, assoc_item_attrs)?);
325 }
326 }
327 cx.expect(TokenKind::close_delim(Brace))?;
328 Ok(DetachedItem {
329 attrs: attrs.normal,
330 path,
331 kind: DetachedItemKind::Trait(DetachedTrait { items, refts }),
332 node_id: cx.next_node_id(),
333 })
334}
335
336fn parse_detached_impl(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
340 let lo = cx.lo();
341 cx.expect(kw::Impl)?;
342 let hi = cx.hi();
343 let span = cx.mk_span(lo, hi);
344 let outer_path = parse_expr_path(cx)?;
345 let _generics = parse_opt_generics(cx)?;
346 let inner_path = if cx.advance_if(kw::For) {
347 let path = parse_expr_path(cx)?;
348 let _generics = parse_opt_generics(cx)?;
349 Some(path)
350 } else {
351 None
352 };
353 cx.expect(TokenKind::open_delim(Brace))?;
354
355 let mut items = vec![];
356 let mut refts = vec![];
357 while !cx.peek(TokenKind::close_delim(Brace)) {
358 let assoc_item_attrs = parse_attrs(cx)?;
360 if assoc_item_attrs.is_reft() && inner_path.is_some() {
361 refts.push(parse_impl_assoc_reft(cx)?);
362 } else {
363 items.push(parse_detached_fn_sig(cx, assoc_item_attrs)?);
364 }
365 }
366 cx.expect(TokenKind::close_delim(Brace))?;
367 if let Some(path) = inner_path {
368 Ok(DetachedItem {
369 attrs: attrs.normal,
370 path,
371 kind: DetachedItemKind::TraitImpl(DetachedTraitImpl {
372 trait_: outer_path,
373 items,
374 refts,
375 span,
376 }),
377 node_id: cx.next_node_id(),
378 })
379 } else {
380 Ok(DetachedItem {
381 attrs: attrs.normal,
382 path: outer_path,
383 kind: DetachedItemKind::InherentImpl(DetachedInherentImpl { items, span }),
384 node_id: cx.next_node_id(),
385 })
386 }
387}
388
389fn parse_attr(cx: &mut ParseCtxt, attrs: &mut ParsedAttrs) -> ParseResult {
390 cx.expect(token::Pound)?;
391 cx.expect(token::OpenBracket)?;
392 let mut lookahead = cx.lookahead1();
393 if lookahead.advance_if(kw::Trusted) {
394 if cx.advance_if(token::OpenParen) {
395 parse_reason(cx)?;
396 cx.expect(token::CloseParen)?;
397 }
398 attrs.normal.push(Attr::Trusted(Trusted::Yes));
399 } else if lookahead.advance_if(sym::hide) {
400 attrs.syntax.push(SyntaxAttr::Hide);
401 } else if lookahead.advance_if(kw::Opaque) {
402 attrs.syntax.push(SyntaxAttr::Opaque);
403 } else if lookahead.advance_if(kw::Reft) {
404 attrs.syntax.push(SyntaxAttr::Reft);
405 } else if lookahead.advance_if(kw::RefinedBy) {
406 attrs
407 .syntax
408 .push(SyntaxAttr::RefinedBy(delimited(cx, Parenthesis, parse_refined_by)?));
409 } else if lookahead.advance_if(kw::Invariant) {
410 attrs
411 .syntax
412 .push(SyntaxAttr::Invariant(delimited(cx, Parenthesis, |cx| parse_expr(cx, true))?));
413 } else {
414 return Err(lookahead.into_error());
415 };
416 cx.expect(token::CloseBracket)
417}
418
419fn parse_attrs(cx: &mut ParseCtxt) -> ParseResult<ParsedAttrs> {
420 let mut attrs = ParsedAttrs::default();
421 repeat_while(cx, token::Pound, |cx| parse_attr(cx, &mut attrs))?;
422 Ok(attrs)
423}
424
425fn parse_reft_func(cx: &mut ParseCtxt) -> ParseResult<SpecFunc> {
433 let attrs = parse_attrs(cx)?;
434 let hide = attrs.is_hide();
435 cx.expect(kw::Fn)?;
436 let name = parse_ident(cx)?;
437 let sort_vars = opt_angle(cx, Comma, parse_ident)?;
438 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
439 cx.expect(token::RArrow)?;
440 let output = parse_sort(cx)?;
441 let body = if cx.peek(token::OpenBrace) {
442 Some(parse_block(cx)?)
443 } else {
444 cx.expect(token::Semi)?;
445 None
446 };
447 Ok(SpecFunc { name, sort_vars, params, output, body, hide })
448}
449
450fn parse_qualifier_kind(cx: &mut ParseCtxt) -> ParseResult<QualifierKind> {
455 let mut lookahead = cx.lookahead1();
456 if lookahead.advance_if(kw::Local) {
457 Ok(QualifierKind::Local)
458 } else if lookahead.advance_if(kw::Invariant) {
459 Ok(QualifierKind::Hint)
460 } else {
461 Ok(QualifierKind::Global)
462 }
463}
464
465fn parse_qualifier(cx: &mut ParseCtxt) -> ParseResult<Qualifier> {
471 let lo = cx.lo();
472 let kind = parse_qualifier_kind(cx)?;
473 cx.expect(kw::Qualifier)?;
474 let mut name = parse_ident(cx)?;
475 let mut params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
476 let expr = parse_block(cx)?;
477 let hi = cx.hi();
478
479 if let QualifierKind::Hint = kind {
480 let mut fvars = expr.free_vars();
481 for param in ¶ms {
482 fvars.remove(¶m.ident);
483 }
484 params.extend(fvars.into_iter().map(|ident| {
485 RefineParam {
486 ident,
487 sort: Sort::Infer,
488 mode: None,
489 span: ident.span,
490 node_id: cx.next_node_id(),
491 }
492 }));
493
494 let span = name.span;
495 let str = format!("{}_{}_{}", name.name.to_ident_string(), span.lo().0, span.hi().0);
496 name = Ident { name: Symbol::intern(&str), ..name };
497 }
498
499 Ok(Qualifier { name, params, expr, span: cx.mk_span(lo, hi), kind })
500}
501
502fn parse_sort_decl(cx: &mut ParseCtxt) -> ParseResult<SortDecl> {
506 cx.expect(kw::Opaque)?;
507 cx.expect(kw::Sort)?;
508 let name = parse_ident(cx)?;
509 let sort_vars = opt_angle(cx, Comma, parse_ident)?;
510 cx.expect(token::Semi)?;
511 Ok(SortDecl { name, sort_vars })
512}
513
514fn parse_binop(cx: &mut ParseCtxt) -> ParseResult<BinOp> {
516 let (op, ntokens) = cx
517 .peek_binop()
518 .ok_or_else(|| cx.unexpected_token(vec![Expected::Str("binary operator")]))?;
519 cx.advance_by(ntokens);
520 Ok(op)
521}
522
523fn parse_primop_property(cx: &mut ParseCtxt) -> ParseResult<PrimOpProp> {
527 let lo = cx.lo();
528 cx.expect(kw::Property)?;
529
530 let name = parse_ident(cx)?;
532
533 cx.expect(token::OpenBracket)?;
535 let op = parse_binop(cx)?;
536 cx.expect(token::CloseBracket)?;
537
538 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::No))?;
540
541 let body = parse_block(cx)?;
542 let hi = cx.hi();
543
544 Ok(PrimOpProp { name, op, params, body, span: cx.mk_span(lo, hi) })
545}
546
547pub(crate) fn parse_trait_assoc_refts(cx: &mut ParseCtxt) -> ParseResult<Vec<TraitAssocReft>> {
548 until(cx, token::Eof, parse_trait_assoc_reft)
549}
550
551fn parse_trait_assoc_reft(cx: &mut ParseCtxt) -> ParseResult<TraitAssocReft> {
557 let lo = cx.lo();
558 let final_ = cx.advance_if(kw::Final);
559 cx.expect(kw::Fn)?;
560 let name = parse_ident(cx)?;
561 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
562 cx.expect(token::RArrow)?;
563 let output = parse_base_sort(cx)?;
564 let body = if cx.peek(token::OpenBrace) {
565 Some(parse_block(cx)?)
566 } else {
567 cx.advance_if(token::Semi);
568 None
569 };
570 let hi = cx.hi();
571 Ok(TraitAssocReft { name, params, output, body, span: cx.mk_span(lo, hi), final_ })
572}
573
574pub(crate) fn parse_impl_assoc_refts(cx: &mut ParseCtxt) -> ParseResult<Vec<ImplAssocReft>> {
575 until(cx, token::Eof, parse_impl_assoc_reft)
576}
577
578fn parse_impl_assoc_reft(cx: &mut ParseCtxt) -> ParseResult<ImplAssocReft> {
582 let lo = cx.lo();
583 cx.expect(kw::Fn)?;
584 let name = parse_ident(cx)?;
585 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
586 cx.expect(token::RArrow)?;
587 let output = parse_base_sort(cx)?;
588 let body = parse_block(cx)?;
589 let hi = cx.hi();
590 Ok(ImplAssocReft { name, params, output, body, span: cx.mk_span(lo, hi) })
591}
592
593pub(crate) fn parse_refined_by(cx: &mut ParseCtxt) -> ParseResult<RefineParams> {
597 punctuated_until(cx, Comma, token::Eof, |cx| parse_refine_param(cx, RequireSort::Yes))
598}
599
600pub(crate) fn parse_variant(cx: &mut ParseCtxt, ret_arrow: bool) -> ParseResult<VariantDef> {
606 let lo = cx.lo();
607 let mut fields = vec![];
608 let mut ret = None;
609 let ident = if ret_arrow || cx.peek2(NonReserved, token::OpenParen) {
610 Some(parse_ident(cx)?)
611 } else {
612 None
613 };
614 if cx.peek(token::OpenParen) || cx.peek(token::OpenBrace) {
615 fields = parse_fields(cx)?;
616 if cx.advance_if(token::RArrow) {
617 ret = Some(parse_variant_ret(cx)?);
618 }
619 } else {
620 if ret_arrow {
621 cx.expect(token::RArrow)?;
622 }
623 ret = Some(parse_variant_ret(cx)?);
624 };
625 let hi = cx.hi();
626 Ok(VariantDef { ident, fields, ret, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
627}
628
629fn parse_fields(cx: &mut ParseCtxt) -> ParseResult<Vec<Ty>> {
633 let mut lookahead = cx.lookahead1();
634 if lookahead.peek(token::OpenParen) {
635 parens(cx, Comma, parse_type)
636 } else if lookahead.peek(token::OpenBrace) {
637 braces(cx, Comma, parse_type)
638 } else {
639 Err(lookahead.into_error())
640 }
641}
642
643fn parse_variant_ret(cx: &mut ParseCtxt) -> ParseResult<VariantRet> {
647 let path = parse_path(cx)?;
648 let indices = if cx.peek(token::OpenBracket) {
649 parse_indices(cx)?
650 } else {
651 let hi = cx.hi();
652 Indices { indices: vec![], span: cx.mk_span(hi, hi) }
653 };
654 Ok(VariantRet { path, indices })
655}
656
657pub(crate) fn parse_type_alias(cx: &mut ParseCtxt) -> ParseResult<TyAlias> {
658 let lo = cx.lo();
659 cx.expect(kw::Type)?;
660 let ident = parse_ident(cx)?;
661 let generics = parse_opt_generics(cx)?;
662 let params = if cx.peek(token::OpenParen) {
663 parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?
664 } else {
665 vec![]
666 };
667 let index = if cx.peek(token::OpenBracket) {
668 Some(delimited(cx, Bracket, |cx| parse_refine_param(cx, RequireSort::Yes))?)
669 } else {
670 None
671 };
672 cx.expect(token::Eq)?;
673 let ty = parse_type(cx)?;
674 let hi = cx.hi();
675 Ok(TyAlias {
676 ident,
677 generics,
678 params,
679 index,
680 ty,
681 node_id: cx.next_node_id(),
682 span: cx.mk_span(lo, hi),
683 })
684}
685
686fn parse_opt_generics(cx: &mut ParseCtxt) -> ParseResult<Generics> {
687 if !cx.peek(LAngle) {
688 let hi = cx.hi();
689 return Ok(Generics { params: vec![], predicates: None, span: cx.mk_span(hi, hi) });
690 }
691 let lo = cx.lo();
692 let params = angle(cx, Comma, parse_generic_param)?;
693 let hi = cx.hi();
694 Ok(Generics { params, predicates: None, span: cx.mk_span(lo, hi) })
695}
696
697fn parse_generic_param(cx: &mut ParseCtxt) -> ParseResult<GenericParam> {
698 let name = parse_ident(cx)?;
699 Ok(GenericParam { name, node_id: cx.next_node_id() })
700}
701
702fn invalid_ident_err(ident: &Ident) -> ParseError {
703 ParseError { kind: crate::ParseErrorKind::InvalidBinding, span: ident.span }
704}
705
706fn mut_as_strg(inputs: Vec<FnInput>, ensures: &[Ensures]) -> ParseResult<Vec<FnInput>> {
707 let locs = ensures
709 .iter()
710 .filter_map(|ens| if let Ensures::Type(ident, _, _) = ens { Some(ident) } else { None })
711 .collect::<HashSet<_>>();
712 let mut res = vec![];
714 for input in inputs {
715 if let FnInput::Ty(Some(ident), _, _) = &input
716 && locs.contains(&ident)
717 {
718 let FnInput::Ty(Some(ident), ty, id) = input else {
720 return Err(invalid_ident_err(ident));
721 };
722 let TyKind::Ref(Mutability::Mut, inner_ty) = ty.kind else {
723 return Err(invalid_ident_err(&ident));
724 };
725 res.push(FnInput::StrgRef(ident, *inner_ty, id));
726 } else {
727 res.push(input);
729 }
730 }
731 Ok(res)
732}
733
734pub(crate) fn parse_fn_sig<T: PeekExpected>(cx: &mut ParseCtxt, end: T) -> ParseResult<FnSig> {
742 let lo = cx.lo();
743 let asyncness = parse_asyncness(cx);
744 cx.expect(kw::Fn)?;
745 let ident = if cx.peek(NonReserved) { Some(parse_ident(cx)?) } else { None };
746 let mut generics = parse_opt_generics(cx)?;
747 let params = if cx.peek(token::OpenBracket) {
748 brackets(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?
749 } else {
750 vec![]
751 };
752 let inputs = parens(cx, Comma, parse_fn_input)?;
753 let returns = parse_fn_ret(cx)?;
754 let requires = parse_opt_requires(cx)?;
755 let ensures = parse_opt_ensures(cx)?;
756 let inputs = mut_as_strg(inputs, &ensures)?;
757 generics.predicates = parse_opt_where(cx)?;
758 cx.expect(end)?;
759 let hi = cx.hi();
760 Ok(FnSig {
761 asyncness,
762 generics,
763 params,
764 ident,
765 inputs,
766 requires,
767 output: FnOutput { returns, ensures, node_id: cx.next_node_id() },
768 node_id: cx.next_node_id(),
769 span: cx.mk_span(lo, hi),
770 })
771}
772
773fn parse_opt_requires(cx: &mut ParseCtxt) -> ParseResult<Vec<Requires>> {
777 if !cx.advance_if(kw::Requires) {
778 return Ok(vec![]);
779 }
780 punctuated_until(
781 cx,
782 Comma,
783 |t: TokenKind| t.is_keyword(kw::Ensures) || t.is_keyword(kw::Where) || t.is_eof(),
784 parse_requires_clause,
785 )
786}
787
788fn parse_requires_clause(cx: &mut ParseCtxt) -> ParseResult<Requires> {
792 let mut params = vec![];
793 if cx.advance_if(kw::Forall) {
794 params = sep1(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
795 cx.expect(token::Dot)?;
796 }
797 let pred = parse_expr(cx, true)?;
798 Ok(Requires { params, pred })
799}
800
801fn parse_opt_ensures(cx: &mut ParseCtxt) -> ParseResult<Vec<Ensures>> {
805 if !cx.advance_if(kw::Ensures) {
806 return Ok(vec![]);
807 }
808 punctuated_until(
809 cx,
810 Comma,
811 |t: TokenKind| t.is_keyword(kw::Where) || t.is_eof(),
812 parse_ensures_clause,
813 )
814}
815
816fn parse_ensures_clause(cx: &mut ParseCtxt) -> ParseResult<Ensures> {
821 if cx.peek2(NonReserved, token::Colon) {
822 let ident = parse_ident(cx)?;
824 cx.expect(token::Colon)?;
825 let ty = parse_type(cx)?;
826 Ok(Ensures::Type(ident, ty, cx.next_node_id()))
827 } else {
828 Ok(Ensures::Pred(parse_expr(cx, true)?))
830 }
831}
832
833fn parse_opt_where(cx: &mut ParseCtxt) -> ParseResult<Option<Vec<WhereBoundPredicate>>> {
834 if !cx.advance_if(kw::Where) {
835 return Ok(None);
836 }
837 Ok(Some(punctuated_until(cx, Comma, token::Eof, parse_where_bound)?))
838}
839
840fn parse_where_bound(cx: &mut ParseCtxt) -> ParseResult<WhereBoundPredicate> {
841 let lo = cx.lo();
842 let bounded_ty = parse_type(cx)?;
843 cx.expect(token::Colon)?;
844 let bounds = parse_generic_bounds(cx)?;
845 let hi = cx.hi();
846 Ok(WhereBoundPredicate { span: cx.mk_span(lo, hi), bounded_ty, bounds })
847}
848
849fn parse_fn_ret(cx: &mut ParseCtxt) -> ParseResult<FnRetTy> {
853 if cx.advance_if(token::RArrow) {
854 Ok(FnRetTy::Ty(Box::new(parse_type(cx)?)))
855 } else {
856 let hi = cx.hi();
857 Ok(FnRetTy::Default(cx.mk_span(hi, hi)))
858 }
859}
860
861fn parse_fn_input(cx: &mut ParseCtxt) -> ParseResult<FnInput> {
868 if cx.peek2(NonReserved, token::Colon) {
869 let bind = parse_ident(cx)?;
870 cx.expect(token::Colon)?;
871 if cx.advance_if2(token::And, kw::Strg) {
872 Ok(FnInput::StrgRef(bind, parse_type(cx)?, cx.next_node_id()))
874 } else if cx.peek(NonReserved) {
875 let path = parse_path(cx)?;
876 if cx.peek3(token::OpenBrace, NonReserved, token::Colon) {
877 let bty = path_to_bty(path);
879 let ty = parse_bty_exists(cx, bty)?;
880 Ok(FnInput::Ty(Some(bind), ty, cx.next_node_id()))
881 } else if cx.peek(token::OpenBrace) {
882 let pred = delimited(cx, Brace, |cx| parse_expr(cx, true))?;
884 Ok(FnInput::Constr(bind, path, pred, cx.next_node_id()))
885 } else {
886 let bty = path_to_bty(path);
888 let ty = parse_bty_rhs(cx, bty)?;
889 Ok(FnInput::Ty(Some(bind), ty, cx.next_node_id()))
890 }
891 } else {
892 Ok(FnInput::Ty(Some(bind), parse_type(cx)?, cx.next_node_id()))
894 }
895 } else {
896 Ok(FnInput::Ty(None, parse_type(cx)?, cx.next_node_id()))
898 }
899}
900
901fn parse_asyncness(cx: &mut ParseCtxt) -> Async {
905 let lo = cx.lo();
906 if cx.advance_if(kw::Async) {
907 Async::Yes { node_id: cx.next_node_id(), span: cx.mk_span(lo, cx.hi()) }
908 } else {
909 Async::No
910 }
911}
912
913pub(crate) fn parse_type(cx: &mut ParseCtxt) -> ParseResult<Ty> {
929 let lo = cx.lo();
930 let mut lookahead = cx.lookahead1();
931 let kind = if lookahead.advance_if(kw::Underscore) {
932 TyKind::Hole
933 } else if lookahead.advance_if(token::OpenParen) {
934 let (mut tys, trailing) =
936 punctuated_with_trailing(cx, Comma, token::CloseParen, parse_type)?;
937 cx.expect(token::CloseParen)?;
938 if tys.len() == 1 && !trailing {
939 return Ok(tys.remove(0));
940 } else {
941 TyKind::Tuple(tys)
942 }
943 } else if lookahead.peek(token::OpenBrace) {
944 delimited(cx, Brace, |cx| {
945 if cx.peek2(NonReserved, AnyOf([token::Comma, token::Dot, token::Colon])) {
946 parse_general_exists(cx)
948 } else {
949 let ty = parse_type(cx)?;
951 cx.expect(token::Or)?;
952 let pred = parse_block_expr(cx)?;
953 Ok(TyKind::Constr(pred, Box::new(ty)))
954 }
955 })?
956 } else if lookahead.advance_if(token::And) {
957 let mutbl = if cx.advance_if(kw::Mut) { Mutability::Mut } else { Mutability::Not };
959 TyKind::Ref(mutbl, Box::new(parse_type(cx)?))
960 } else if lookahead.advance_if(token::OpenBracket) {
961 let ty = parse_type(cx)?;
962 if cx.advance_if(token::Semi) {
963 let len = parse_const_arg(cx)?;
965 cx.expect(token::CloseBracket)?;
966 TyKind::Array(Box::new(ty), len)
967 } else {
968 cx.expect(token::CloseBracket)?;
970 let span = cx.mk_span(lo, cx.hi());
971 let kind = BaseTyKind::Slice(Box::new(ty));
972 return parse_bty_rhs(cx, BaseTy { kind, span });
973 }
974 } else if lookahead.advance_if(kw::Impl) {
975 TyKind::ImplTrait(cx.next_node_id(), parse_generic_bounds(cx)?)
977 } else if lookahead.peek(NonReserved) {
978 let path = parse_path(cx)?;
980 let bty = path_to_bty(path);
981 return parse_bty_rhs(cx, bty);
982 } else if lookahead.peek(LAngle) {
983 let bty = parse_qpath(cx)?;
985 return parse_bty_rhs(cx, bty);
986 } else {
987 return Err(lookahead.into_error());
988 };
989 let hi = cx.hi();
990 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
991}
992
993fn parse_qpath(cx: &mut ParseCtxt) -> ParseResult<BaseTy> {
997 let lo = cx.lo();
998 cx.expect(LAngle)?;
999 let qself = parse_type(cx)?;
1000 cx.expect(kw::As)?;
1001 let mut segments = parse_segments(cx)?;
1002 cx.expect(RAngle)?;
1003 cx.expect(token::PathSep)?;
1004 segments.extend(parse_segments(cx)?);
1005 let hi = cx.hi();
1006
1007 let span = cx.mk_span(lo, hi);
1008 let path = Path { segments, refine: vec![], node_id: cx.next_node_id(), span };
1009 let kind = BaseTyKind::Path(Some(Box::new(qself)), path);
1010 Ok(BaseTy { kind, span })
1011}
1012
1013fn parse_general_exists(cx: &mut ParseCtxt) -> ParseResult<TyKind> {
1017 let params = sep1(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
1018 cx.expect(token::Dot)?;
1019 let ty = parse_type(cx)?;
1020 let pred = if cx.advance_if(token::Or) { Some(parse_block_expr(cx)?) } else { None };
1021 Ok(TyKind::GeneralExists { params, ty: Box::new(ty), pred })
1022}
1023
1024fn parse_bty_rhs(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
1030 let lo = bty.span.lo();
1031 if cx.peek(token::OpenBracket) {
1032 let indices = parse_indices(cx)?;
1034 let hi = cx.hi();
1035 let kind = TyKind::Indexed { bty, indices };
1036 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1037 } else if cx.peek(token::OpenBrace) {
1038 parse_bty_exists(cx, bty)
1040 } else {
1041 let hi = cx.hi();
1043 let kind = TyKind::Base(bty);
1044 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1045 }
1046}
1047
1048fn parse_bty_exists(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
1052 let lo = bty.span.lo();
1053 delimited(cx, Brace, |cx| {
1054 let bind = parse_ident(cx)?;
1055 cx.expect(token::Colon)?;
1056 let pred = parse_block_expr(cx)?;
1057 let hi = cx.hi();
1058 let kind = TyKind::Exists { bind, bty, pred };
1059 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1060 })
1061}
1062
1063fn path_to_bty(path: Path) -> BaseTy {
1064 let span = path.span;
1065 BaseTy { kind: BaseTyKind::Path(None, path), span }
1066}
1067
1068fn parse_indices(cx: &mut ParseCtxt) -> ParseResult<Indices> {
1069 let lo = cx.lo();
1070 let indices = brackets(cx, Comma, parse_refine_arg)?;
1071 let hi = cx.hi();
1072 Ok(Indices { indices, span: cx.mk_span(lo, hi) })
1073}
1074
1075fn parse_fn_bound_input(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1076 let lo = cx.lo();
1077 let tys = parens(cx, Comma, parse_type)?;
1078 let hi = cx.hi();
1079 let kind = TyKind::Tuple(tys);
1080 let span = cx.mk_span(lo, hi);
1081 let in_ty = Ty { kind, node_id: cx.next_node_id(), span };
1082 Ok(GenericArg { kind: GenericArgKind::Type(in_ty), node_id: cx.next_node_id() })
1083}
1084
1085fn parse_fn_bound_output(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1086 let lo = cx.lo();
1087
1088 let ty = if cx.advance_if(token::RArrow) {
1089 parse_type(cx)?
1090 } else {
1091 Ty { kind: TyKind::Tuple(vec![]), node_id: cx.next_node_id(), span: cx.mk_span(lo, lo) }
1092 };
1093 let hi = cx.hi();
1094 let ident = Ident { name: Output, span: cx.mk_span(lo, hi) };
1095 Ok(GenericArg { kind: GenericArgKind::Constraint(ident, ty), node_id: cx.next_node_id() })
1096}
1097
1098fn parse_fn_bound_path(cx: &mut ParseCtxt) -> ParseResult<Path> {
1099 let lo = cx.lo();
1100 let ident = parse_ident(cx)?;
1101 let in_arg = parse_fn_bound_input(cx)?;
1102 let out_arg = parse_fn_bound_output(cx)?;
1103 let args = vec![in_arg, out_arg];
1104 let segment = PathSegment { ident, args, node_id: cx.next_node_id() };
1105 let hi = cx.hi();
1106 Ok(Path {
1107 segments: vec![segment],
1108 refine: vec![],
1109 node_id: cx.next_node_id(),
1110 span: cx.mk_span(lo, hi),
1111 })
1112}
1113
1114fn parse_generic_bounds(cx: &mut ParseCtxt) -> ParseResult<GenericBounds> {
1115 let path = if cx.peek(sym::FnOnce) || cx.peek(sym::FnMut) || cx.peek(sym::Fn) {
1116 parse_fn_bound_path(cx)?
1117 } else {
1118 parse_path(cx)?
1119 };
1120 Ok(vec![TraitRef { path, node_id: cx.next_node_id() }])
1121}
1122
1123fn parse_const_arg(cx: &mut ParseCtxt) -> ParseResult<ConstArg> {
1124 let lo = cx.lo();
1125 let mut lookahead = cx.lookahead1();
1126 let kind = if lookahead.peek(AnyLit) {
1127 let len = parse_int(cx)?;
1128 ConstArgKind::Lit(len)
1129 } else if lookahead.advance_if(kw::Underscore) {
1130 ConstArgKind::Infer
1131 } else {
1132 return Err(lookahead.into_error());
1133 };
1134 let hi = cx.hi();
1135 Ok(ConstArg { kind, span: cx.mk_span(lo, hi) })
1136}
1137
1138fn parse_path(cx: &mut ParseCtxt) -> ParseResult<Path> {
1142 let lo = cx.lo();
1143 let segments = parse_segments(cx)?;
1144 let refine =
1145 if cx.peek(token::OpenParen) { parens(cx, Comma, parse_refine_arg)? } else { vec![] };
1146 let hi = cx.hi();
1147 Ok(Path { segments, refine, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1148}
1149
1150fn parse_segments(cx: &mut ParseCtxt) -> ParseResult<Vec<PathSegment>> {
1154 sep1(cx, token::PathSep, parse_segment)
1155}
1156
1157fn parse_segment(cx: &mut ParseCtxt) -> ParseResult<PathSegment> {
1161 let ident = parse_ident(cx)?;
1162 let args = opt_angle(cx, Comma, parse_generic_arg)?;
1163 Ok(PathSegment { ident, node_id: cx.next_node_id(), args })
1164}
1165
1166fn parse_generic_arg(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1170 let kind = if cx.peek2(NonReserved, token::Eq) {
1171 let ident = parse_ident(cx)?;
1172 cx.expect(token::Eq)?;
1173 let ty = parse_type(cx)?;
1174 GenericArgKind::Constraint(ident, ty)
1175 } else {
1176 GenericArgKind::Type(parse_type(cx)?)
1177 };
1178 Ok(GenericArg { kind, node_id: cx.next_node_id() })
1179}
1180
1181fn parse_refine_arg(cx: &mut ParseCtxt) -> ParseResult<RefineArg> {
1188 let lo = cx.lo();
1189 let arg = if cx.advance_if(token::At) {
1190 let bind = parse_ident(cx)?;
1192 let hi = cx.hi();
1193 RefineArg::Bind(bind, BindKind::At, cx.mk_span(lo, hi), cx.next_node_id())
1194 } else if cx.peek2(token::Pound, NonReserved) {
1195 cx.expect(token::Pound)?;
1197 let bind = parse_ident(cx)?;
1198 let hi = cx.hi();
1199 RefineArg::Bind(bind, BindKind::Pound, cx.mk_span(lo, hi), cx.next_node_id())
1200 } else if cx.advance_if(Or) {
1201 let params =
1202 punctuated_until(cx, Comma, Or, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
1203 cx.expect(Or)?;
1204 let body = parse_expr(cx, true)?;
1205 let hi = cx.hi();
1206 RefineArg::Abs(params, body, cx.mk_span(lo, hi), cx.next_node_id())
1207 } else {
1208 RefineArg::Expr(parse_expr(cx, true)?)
1210 };
1211 Ok(arg)
1212}
1213
1214enum RequireSort {
1216 Yes,
1218 Maybe,
1220 No,
1222}
1223
1224fn parse_sort_if_required(cx: &mut ParseCtxt, require_sort: RequireSort) -> ParseResult<Sort> {
1225 match require_sort {
1226 RequireSort::No => Ok(Sort::Infer),
1227 RequireSort::Maybe => {
1228 if cx.advance_if(token::Colon) {
1229 parse_sort(cx)
1230 } else {
1231 Ok(Sort::Infer)
1232 }
1233 }
1234 RequireSort::Yes => {
1235 cx.expect(token::Colon)?;
1236 parse_sort(cx)
1237 }
1238 }
1239}
1240
1241fn parse_refine_param(cx: &mut ParseCtxt, require_sort: RequireSort) -> ParseResult<RefineParam> {
1247 let lo = cx.lo();
1248 let mode = parse_opt_param_mode(cx);
1249 let ident = parse_ident(cx)?;
1250 let sort = parse_sort_if_required(cx, require_sort)?;
1251 let hi = cx.hi();
1252 Ok(RefineParam { mode, ident, sort, span: cx.mk_span(lo, hi), node_id: cx.next_node_id() })
1253}
1254
1255fn parse_opt_param_mode(cx: &mut ParseCtxt) -> Option<ParamMode> {
1259 if cx.advance_if(kw::Hrn) {
1260 Some(ParamMode::Horn)
1261 } else if cx.advance_if(kw::Hdl) {
1262 Some(ParamMode::Hindley)
1263 } else {
1264 None
1265 }
1266}
1267
1268pub(crate) fn parse_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1269 parse_binops(cx, Precedence::MIN, allow_struct)
1270}
1271
1272fn parse_binops(cx: &mut ParseCtxt, base: Precedence, allow_struct: bool) -> ParseResult<Expr> {
1273 let mut lhs = unary_expr(cx, allow_struct)?;
1274 loop {
1275 let lo = cx.lo();
1276 let Some((op, ntokens)) = cx.peek_binop() else { break };
1277 let precedence = Precedence::of_binop(&op);
1278 if precedence < base {
1279 break;
1280 }
1281 cx.advance_by(ntokens);
1282 let next = match precedence.associativity() {
1283 Associativity::Right => precedence,
1284 Associativity::Left => precedence.next(),
1285 Associativity::None => {
1286 if let ExprKind::BinaryOp(op, ..) = &lhs.kind
1287 && Precedence::of_binop(op) == precedence
1288 {
1289 return Err(cx.cannot_be_chained(lo, cx.hi()));
1290 }
1291 precedence.next()
1292 }
1293 };
1294 let rhs = parse_binops(cx, next, allow_struct)?;
1295 let span = lhs.span.to(rhs.span);
1296 lhs = Expr {
1297 kind: ExprKind::BinaryOp(op, Box::new([lhs, rhs])),
1298 node_id: cx.next_node_id(),
1299 span,
1300 }
1301 }
1302 Ok(lhs)
1303}
1304
1305fn unary_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1309 let lo = cx.lo();
1310 let kind = if cx.advance_if(token::Minus) {
1311 ExprKind::UnaryOp(UnOp::Neg, Box::new(unary_expr(cx, allow_struct)?))
1312 } else if cx.advance_if(token::Bang) {
1313 ExprKind::UnaryOp(UnOp::Not, Box::new(unary_expr(cx, allow_struct)?))
1314 } else {
1315 return parse_trailer_expr(cx, allow_struct);
1316 };
1317 let hi = cx.hi();
1318 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1319}
1320
1321fn parse_trailer_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1327 let lo = cx.lo();
1328 let mut e = parse_atom(cx, allow_struct)?;
1329 loop {
1330 let kind = if cx.advance_if(token::Dot) {
1331 let field = parse_ident(cx)?;
1333 ExprKind::Dot(Box::new(e), field)
1334 } else if cx.peek(token::OpenParen) {
1335 let args = parens(cx, Comma, |cx| parse_expr(cx, true))?;
1337 ExprKind::Call(Box::new(e), args)
1338 } else {
1339 break;
1340 };
1341 let hi = cx.hi();
1342 e = Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) };
1343 }
1344 Ok(e)
1345}
1346
1347fn parse_atom(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1360 let lo = cx.lo();
1361 let mut lookahead = cx.lookahead1();
1362 if lookahead.peek(kw::If) {
1363 parse_if_expr(cx)
1365 } else if lookahead.peek(AnyLit) {
1366 parse_lit(cx)
1368 } else if lookahead.peek(token::OpenParen) {
1369 delimited(cx, Parenthesis, |cx| parse_expr(cx, true))
1370 } else if lookahead.advance_if(token::Pound) {
1371 let lo = cx.lo();
1373 let exprs = braces(cx, Comma, |cx| parse_expr(cx, true))?;
1374 let hi = cx.hi();
1375 let kind = ExprKind::SetLiteral(exprs);
1376 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1377 } else if lookahead.peek(NonReserved) {
1378 let path = parse_expr_path(cx)?;
1379 let kind = if allow_struct && cx.peek(token::OpenBrace) {
1380 let args = braces(cx, Comma, parse_constructor_arg)?;
1382 ExprKind::Constructor(Some(path), args)
1383 } else {
1384 ExprKind::Path(path)
1386 };
1387 let hi = cx.hi();
1388 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1389 } else if allow_struct && lookahead.peek(token::OpenBrace) {
1390 let args = braces(cx, Comma, parse_constructor_arg)?;
1392 let hi = cx.hi();
1393 Ok(Expr {
1394 kind: ExprKind::Constructor(None, args),
1395 node_id: cx.next_node_id(),
1396 span: cx.mk_span(lo, hi),
1397 })
1398 } else if lookahead.advance_if(LAngle) {
1399 let lo = cx.lo();
1401 let qself = parse_type(cx)?;
1402 cx.expect(kw::As)?;
1403 let path = parse_path(cx)?;
1404 cx.expect(RAngle)?;
1405 cx.expect(token::PathSep)?;
1406 let name = parse_ident(cx)?;
1407 let hi = cx.hi();
1408 let kind = ExprKind::AssocReft(Box::new(qself), path, name);
1409 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1410 } else if lookahead.peek(token::OpenBracket) {
1411 parse_prim_uif(cx)
1412 } else if lookahead.peek(kw::Exists) || lookahead.peek(kw::Forall) {
1413 parse_bounded_quantifier(cx)
1414 } else {
1415 Err(lookahead.into_error())
1416 }
1417}
1418
1419fn parse_prim_uif(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1420 let lo = cx.lo();
1421 cx.expect(token::OpenBracket)?;
1422 let op = parse_binop(cx)?;
1423 cx.expect(token::CloseBracket)?;
1424 let hi = cx.hi();
1425 Ok(Expr { kind: ExprKind::PrimUIF(op), node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1426}
1427
1428fn parse_bounded_quantifier(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1433 let lo = cx.lo();
1434 let mut lookahead = cx.lookahead1();
1435 let quant = if lookahead.advance_if(kw::Forall) {
1436 QuantKind::Forall
1437 } else if lookahead.advance_if(kw::Exists) {
1438 QuantKind::Exists
1439 } else {
1440 return Err(lookahead.into_error());
1441 };
1442 let param = parse_refine_param(cx, RequireSort::Maybe)?;
1443 cx.expect(kw::In)?;
1444 let start = parse_int(cx)?;
1445 cx.expect(token::DotDot)?;
1446 let end = parse_int(cx)?;
1447 let body = parse_block(cx)?;
1448 let hi = cx.hi();
1449 Ok(Expr {
1450 kind: ExprKind::BoundedQuant(quant, param, start..end, Box::new(body)),
1451 node_id: cx.next_node_id(),
1452 span: cx.mk_span(lo, hi),
1453 })
1454}
1455
1456fn parse_constructor_arg(cx: &mut ParseCtxt) -> ParseResult<ConstructorArg> {
1460 let lo = cx.lo();
1461 let mut lookahead = cx.lookahead1();
1462 if lookahead.peek(NonReserved) {
1463 let ident = parse_ident(cx)?;
1464 cx.expect(token::Colon)?;
1465 let expr = parse_expr(cx, true)?;
1466 let hi = cx.hi();
1467 Ok(ConstructorArg::FieldExpr(FieldExpr {
1468 ident,
1469 expr,
1470 node_id: cx.next_node_id(),
1471 span: cx.mk_span(lo, hi),
1472 }))
1473 } else if lookahead.advance_if(token::DotDot) {
1474 let spread = parse_expr(cx, true)?;
1475 let hi = cx.hi();
1476 Ok(ConstructorArg::Spread(Spread {
1477 expr: spread,
1478 node_id: cx.next_node_id(),
1479 span: cx.mk_span(lo, hi),
1480 }))
1481 } else {
1482 Err(lookahead.into_error())
1483 }
1484}
1485
1486fn parse_expr_path(cx: &mut ParseCtxt) -> ParseResult<ExprPath> {
1488 let lo = cx.lo();
1489 let segments = sep1(cx, token::PathSep, parse_expr_path_segment)?;
1490 let hi = cx.hi();
1491 Ok(ExprPath { segments, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1492}
1493
1494fn parse_expr_path_segment(cx: &mut ParseCtxt) -> ParseResult<ExprPathSegment> {
1495 Ok(ExprPathSegment { ident: parse_ident(cx)?, node_id: cx.next_node_id() })
1496}
1497
1498fn parse_if_expr(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1502 let mut branches = vec![];
1503
1504 loop {
1505 let lo = cx.lo();
1506 cx.expect(kw::If)?;
1507 let cond = parse_expr(cx, false)?;
1508 let then_ = parse_block(cx)?;
1509 branches.push((lo, cond, then_));
1510 cx.expect(kw::Else)?;
1511
1512 if !cx.peek(kw::If) {
1513 break;
1514 }
1515 }
1516 let mut else_ = parse_block(cx)?;
1517
1518 let hi = cx.hi();
1519 while let Some((lo, cond, then_)) = branches.pop() {
1520 else_ = Expr {
1521 kind: ExprKind::IfThenElse(Box::new([cond, then_, else_])),
1522 node_id: cx.next_node_id(),
1523 span: cx.mk_span(lo, hi),
1524 };
1525 }
1526 Ok(else_)
1527}
1528
1529fn parse_block(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1531 delimited(cx, Brace, parse_block_expr)
1532}
1533
1534fn parse_block_expr(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1536 let lo = cx.lo();
1537 let decls = repeat_while(cx, kw::Let, parse_let_decl)?;
1538 let body = parse_expr(cx, true)?;
1539 let hi = cx.hi();
1540
1541 if decls.is_empty() {
1542 Ok(body)
1543 } else {
1544 let kind = ExprKind::Block(decls, Box::new(body));
1545 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1546 }
1547}
1548
1549fn parse_let_decl(cx: &mut ParseCtxt) -> ParseResult<LetDecl> {
1551 cx.expect(kw::Let)?;
1552 let param = parse_refine_param(cx, RequireSort::Maybe)?;
1553 cx.expect(token::Eq)?;
1554 let init = parse_expr(cx, true)?;
1555 cx.expect(token::Semi)?;
1556 Ok(LetDecl { param, init })
1557}
1558
1559fn parse_lit(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1563 if let Token { kind: token::Literal(lit), lo, hi } = cx.at(0) {
1564 cx.advance();
1565 Ok(Expr {
1566 kind: ExprKind::Literal(lit),
1567 node_id: cx.next_node_id(),
1568 span: cx.mk_span(lo, hi),
1569 })
1570 } else {
1571 Err(cx.unexpected_token(vec![AnyLit.expected()]))
1572 }
1573}
1574
1575fn parse_ident(cx: &mut ParseCtxt) -> ParseResult<Ident> {
1576 if let Token { kind: token::Ident(name, is_raw), lo, hi } = cx.at(0)
1577 && (!cx.is_reserved(name) || is_raw == IdentIsRaw::Yes)
1578 {
1579 cx.advance();
1580 return Ok(Ident { name, span: cx.mk_span(lo, hi) });
1581 }
1582 Err(cx.unexpected_token(vec![NonReserved.expected()]))
1583}
1584
1585fn parse_int<T: FromStr>(cx: &mut ParseCtxt) -> ParseResult<T> {
1586 if let token::Literal(lit) = cx.at(0).kind
1587 && let LitKind::Integer = lit.kind
1588 && let Ok(value) = lit.symbol.as_str().parse::<T>()
1589 {
1590 cx.advance();
1591 return Ok(value);
1592 }
1593
1594 Err(cx.unexpected_token(vec![Expected::Str(std::any::type_name::<T>())]))
1595}
1596
1597fn parse_sort(cx: &mut ParseCtxt) -> ParseResult<Sort> {
1603 if cx.peek(token::OpenParen) {
1604 let inputs = parens(cx, Comma, parse_base_sort)?;
1606 cx.expect(token::RArrow)?;
1607 let output = parse_base_sort(cx)?;
1608 Ok(Sort::Func { inputs, output })
1609 } else {
1610 let bsort = parse_base_sort(cx)?;
1611 if cx.advance_if(token::RArrow) {
1612 let output = parse_base_sort(cx)?;
1614 Ok(Sort::Func { inputs: vec![bsort], output })
1615 } else {
1616 Ok(Sort::Base(bsort))
1618 }
1619 }
1620}
1621
1622fn parse_base_sort(cx: &mut ParseCtxt) -> ParseResult<BaseSort> {
1629 if cx.advance_if(kw::Bitvec) {
1630 cx.expect(LAngle)?;
1632 let len = parse_int(cx)?;
1633 cx.expect(RAngle)?;
1634 Ok(BaseSort::BitVec(len))
1635 } else if cx.advance_if(LAngle) {
1636 let qself = parse_type(cx)?;
1638 cx.expect(kw::As)?;
1639 let mut path = parse_path(cx)?;
1640 cx.expect(RAngle)?;
1641 cx.expect(token::PathSep)?;
1642 path.segments.push(parse_segment(cx)?);
1643 Ok(BaseSort::SortOf(Box::new(qself), path))
1644 } else {
1645 let segments = sep1(cx, token::PathSep, parse_ident)?;
1647 let args = opt_angle(cx, Comma, parse_base_sort)?;
1648 let path = SortPath { segments, args, node_id: cx.next_node_id() };
1649 Ok(BaseSort::Path(path))
1650 }
1651}
1652
1653#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
1655enum Precedence {
1656 Iff,
1658 Implies,
1660 Or,
1662 And,
1664 Compare,
1666 BitOr,
1668 BitXor,
1670 BitAnd,
1672 Shift,
1674 Sum,
1676 Product,
1678 Prefix,
1680}
1681
1682enum Associativity {
1683 Right,
1684 Left,
1685 None,
1686}
1687
1688impl Precedence {
1689 const MIN: Self = Precedence::Iff;
1690
1691 fn of_binop(op: &BinOp) -> Precedence {
1692 match op {
1693 BinOp::Iff => Precedence::Iff,
1694 BinOp::Imp => Precedence::Implies,
1695 BinOp::Or => Precedence::Or,
1696 BinOp::And => Precedence::And,
1697 BinOp::Eq | BinOp::Ne | BinOp::Gt | BinOp::Ge | BinOp::Lt | BinOp::Le => {
1698 Precedence::Compare
1699 }
1700 BinOp::BitOr => Precedence::BitOr,
1701 BinOp::BitXor => Precedence::BitXor,
1702 BinOp::BitAnd => Precedence::BitAnd,
1703 BinOp::BitShl | BinOp::BitShr => Precedence::Shift,
1704 BinOp::Add | BinOp::Sub => Precedence::Sum,
1705 BinOp::Mul | BinOp::Div | BinOp::Mod => Precedence::Product,
1706 }
1707 }
1708
1709 fn next(self) -> Precedence {
1710 match self {
1711 Precedence::Iff => Precedence::Implies,
1712 Precedence::Implies => Precedence::Or,
1713 Precedence::Or => Precedence::And,
1714 Precedence::And => Precedence::Compare,
1715 Precedence::Compare => Precedence::BitOr,
1716 Precedence::BitOr => Precedence::BitXor,
1717 Precedence::BitXor => Precedence::BitAnd,
1718 Precedence::BitAnd => Precedence::Shift,
1719 Precedence::Shift => Precedence::Sum,
1720 Precedence::Sum => Precedence::Product,
1721 Precedence::Product => Precedence::Prefix,
1722 Precedence::Prefix => Precedence::Prefix,
1723 }
1724 }
1725
1726 fn associativity(self) -> Associativity {
1727 match self {
1728 Precedence::Or
1729 | Precedence::And
1730 | Precedence::BitOr
1731 | Precedence::BitXor
1732 | Precedence::BitAnd
1733 | Precedence::Shift
1734 | Precedence::Sum
1735 | Precedence::Product => Associativity::Left,
1736 Precedence::Compare | Precedence::Iff => Associativity::None,
1737 Precedence::Implies | Precedence::Prefix => Associativity::Right,
1738 }
1739 }
1740}