1pub(crate) mod lookahead;
2mod utils;
3use std::{collections::HashSet, str::FromStr, vec};
4
5use lookahead::{AnyIdent, AnyLit, LAngle, RAngle};
6use rustc_span::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, Peek as _,
14 lexer::{
15 Delimiter::*,
16 Token::{self as Tok, Caret, CloseDelim, Comma, OpenDelim},
17 },
18 surface::{
19 Async, BaseSort, BaseTy, BaseTyKind, BinOp, BindKind, ConstArg, ConstArgKind,
20 ConstructorArg, Ensures, Expr, ExprKind, ExprPath, ExprPathSegment, FieldExpr, FnInput,
21 FnOutput, FnRetTy, FnSig, GenericArg, GenericArgKind, GenericBounds, GenericParam,
22 GenericParamKind, Generics, Ident, ImplAssocReft, Indices, Item, LetDecl, LitKind,
23 Mutability, ParamMode, Path, PathSegment, QualNames, Qualifier, QuantKind, RefineArg,
24 RefineParam, RefineParams, Requires, RevealNames, Sort, SortDecl, SortPath, SpecFunc,
25 Spread, TraitAssocReft, TraitRef, Ty, TyAlias, TyKind, UnOp, VariantDef, VariantRet,
26 WhereBoundPredicate,
27 },
28};
29pub(crate) fn parse_yes_or_no_with_reason(cx: &mut ParseCtxt) -> ParseResult<bool> {
35 let mut lookahead = cx.lookahead1();
36 if lookahead.advance_if("yes") {
37 if cx.advance_if(Tok::Comma) {
38 parse_reason(cx)?;
39 }
40 Ok(true)
41 } else if lookahead.advance_if("no") {
42 if cx.advance_if(Tok::Comma) {
43 parse_reason(cx)?;
44 }
45 Ok(false)
46 } else if lookahead.peek("reason") {
47 parse_reason(cx)?;
48 Ok(true)
49 } else {
50 Err(lookahead.into_error())
51 }
52}
53
54fn parse_reason(cx: &mut ParseCtxt) -> ParseResult {
58 cx.expect("reason")?;
59 cx.expect(Tok::Eq)?;
60 cx.expect(AnyLit)
61}
62
63pub(crate) fn parse_qual_names(cx: &mut ParseCtxt) -> ParseResult<QualNames> {
67 let names = punctuated_until(cx, Comma, Tok::Eof, parse_ident)?;
68 Ok(QualNames { names })
69}
70
71pub(crate) fn parse_reveal_names(cx: &mut ParseCtxt) -> ParseResult<RevealNames> {
72 let names = punctuated_until(cx, Comma, Tok::Eof, parse_ident)?;
73 Ok(RevealNames { names })
74}
75
76pub(crate) fn parse_generics(cx: &mut ParseCtxt) -> ParseResult<Generics> {
77 let lo = cx.lo();
78 let params = punctuated_until(cx, Comma, Tok::Eof, parse_generic_param)?;
79 let hi = cx.hi();
80 Ok(Generics { params, predicates: None, span: cx.mk_span(lo, hi) })
81}
82
83pub(crate) fn parse_flux_items(cx: &mut ParseCtxt) -> ParseResult<Vec<Item>> {
84 until(cx, Tok::Eof, parse_flux_item)
85}
86
87fn parse_flux_item(cx: &mut ParseCtxt) -> ParseResult<Item> {
88 let mut lookahead = cx.lookahead1();
89 if lookahead.peek([Tok::Pound, Tok::Fn]) {
90 parse_reft_func(cx).map(Item::FuncDef)
91 } else if lookahead.peek([Tok::Local, Tok::Qualifier]) {
92 parse_qualifier(cx).map(Item::Qualifier)
93 } else if lookahead.peek(Tok::Opaque) {
94 parse_sort_decl(cx).map(Item::SortDecl)
95 } else {
96 Err(lookahead.into_error())
97 }
98}
99
100fn parse_hide_attr(cx: &mut ParseCtxt) -> ParseResult<bool> {
101 if !cx.advance_if(Tok::Pound) {
102 return Ok(false);
103 }
104 cx.expect(Tok::OpenDelim(Bracket))?;
105 cx.expect("hide")?;
106 cx.expect(Tok::CloseDelim(Bracket))?;
107 Ok(true)
108}
109
110fn parse_reft_func(cx: &mut ParseCtxt) -> ParseResult<SpecFunc> {
111 let hide = parse_hide_attr(cx)?;
112 cx.expect(Tok::Fn)?;
113 let name = parse_ident(cx)?;
114 let sort_vars = opt_angle(cx, Comma, parse_ident)?;
115 let params = parens(cx, Comma, |cx| parse_refine_param(cx, true))?;
116 cx.expect(Tok::RArrow)?;
117 let output = parse_sort(cx)?;
118 let body = if cx.peek(OpenDelim(Brace)) {
119 Some(parse_block(cx)?)
120 } else {
121 cx.expect(Tok::Semi)?;
122 None
123 };
124 Ok(SpecFunc { name, sort_vars, params, output, body, hide })
125}
126
127fn parse_qualifier(cx: &mut ParseCtxt) -> ParseResult<Qualifier> {
128 let lo = cx.lo();
129 let local = cx.advance_if(Tok::Local);
130 cx.expect(Tok::Qualifier)?;
131 let name = parse_ident(cx)?;
132 let params = parens(cx, Comma, |cx| parse_refine_param(cx, true))?;
133 let expr = parse_block(cx)?;
134 let hi = cx.hi();
135 Ok(Qualifier { global: !local, name, params, expr, span: cx.mk_span(lo, hi) })
136}
137
138fn parse_sort_decl(cx: &mut ParseCtxt) -> ParseResult<SortDecl> {
139 cx.expect(Tok::Opaque)?;
140 cx.expect(Tok::Sort)?;
141 let name = parse_ident(cx)?;
142 cx.expect(Tok::Semi)?;
143 Ok(SortDecl { name })
144}
145
146pub(crate) fn parse_trait_assoc_refts(cx: &mut ParseCtxt) -> ParseResult<Vec<TraitAssocReft>> {
147 until(cx, Tok::Eof, parse_trait_assoc_reft)
148}
149
150fn parse_trait_assoc_reft(cx: &mut ParseCtxt) -> ParseResult<TraitAssocReft> {
155 let lo = cx.lo();
156 cx.expect(Tok::Fn)?;
157 let name = parse_ident(cx)?;
158 let params = parens(cx, Comma, |cx| parse_refine_param(cx, true))?;
159 cx.expect(Tok::RArrow)?;
160 let output = parse_base_sort(cx)?;
161 let body = if cx.peek(OpenDelim(Brace)) {
162 Some(parse_block(cx)?)
163 } else {
164 cx.advance_if(Tok::Semi);
165 None
166 };
167 let hi = cx.hi();
168 Ok(TraitAssocReft { name, params, output, body, span: cx.mk_span(lo, hi) })
169}
170
171pub(crate) fn parse_impl_assoc_refts(cx: &mut ParseCtxt) -> ParseResult<Vec<ImplAssocReft>> {
172 until(cx, Tok::Eof, parse_impl_assoc_reft)
173}
174
175fn parse_impl_assoc_reft(cx: &mut ParseCtxt) -> ParseResult<ImplAssocReft> {
179 let lo = cx.lo();
180 cx.expect(Tok::Fn)?;
181 let name = parse_ident(cx)?;
182 let params = parens(cx, Comma, |cx| parse_refine_param(cx, true))?;
183 cx.expect(Tok::RArrow)?;
184 let output = parse_base_sort(cx)?;
185 let body = parse_block(cx)?;
186 let hi = cx.hi();
187 Ok(ImplAssocReft { name, params, output, body, span: cx.mk_span(lo, hi) })
188}
189
190pub(crate) fn parse_refined_by(cx: &mut ParseCtxt) -> ParseResult<RefineParams> {
194 punctuated_until(cx, Comma, Tok::Eof, |cx| parse_refine_param(cx, true))
195}
196
197pub(crate) fn parse_variant(cx: &mut ParseCtxt) -> ParseResult<VariantDef> {
203 let lo = cx.lo();
204 let mut fields = vec![];
205 let mut ret = None;
206 if cx.peek([OpenDelim(Parenthesis), OpenDelim(Brace)]) {
207 fields = parse_fields(cx)?;
208 if cx.advance_if(Tok::RArrow) {
209 ret = Some(parse_variant_ret(cx)?);
210 }
211 } else {
212 ret = Some(parse_variant_ret(cx)?);
213 };
214 let hi = cx.hi();
215 Ok(VariantDef { fields, ret, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
216}
217
218fn parse_fields(cx: &mut ParseCtxt) -> ParseResult<Vec<Ty>> {
222 let mut lookahead = cx.lookahead1();
223 if lookahead.peek(OpenDelim(Parenthesis)) {
224 parens(cx, Comma, parse_type)
225 } else if lookahead.peek(OpenDelim(Brace)) {
226 braces(cx, Comma, parse_type)
227 } else {
228 Err(lookahead.into_error())
229 }
230}
231
232fn parse_variant_ret(cx: &mut ParseCtxt) -> ParseResult<VariantRet> {
236 let path = parse_path(cx)?;
237 let indices = if cx.peek(OpenDelim(Bracket)) {
238 parse_indices(cx)?
239 } else {
240 let hi = cx.hi();
241 Indices { indices: vec![], span: cx.mk_span(hi, hi) }
242 };
243 Ok(VariantRet { path, indices })
244}
245
246pub(crate) fn parse_type_alias(cx: &mut ParseCtxt) -> ParseResult<TyAlias> {
247 let lo = cx.lo();
248 cx.expect(Tok::Type)?;
249 let ident = parse_ident(cx)?;
250 let generics = parse_opt_generics(cx)?;
251 let params = if cx.peek(OpenDelim(Parenthesis)) {
252 parens(cx, Comma, |cx| parse_refine_param(cx, true))?
253 } else {
254 vec![]
255 };
256 let index = if cx.peek(OpenDelim(Bracket)) {
257 Some(delimited(cx, Bracket, |cx| parse_refine_param(cx, true))?)
258 } else {
259 None
260 };
261 cx.expect(Tok::Eq)?;
262 let ty = parse_type(cx)?;
263 let hi = cx.hi();
264 Ok(TyAlias {
265 ident,
266 generics,
267 params,
268 index,
269 ty,
270 node_id: cx.next_node_id(),
271 span: cx.mk_span(lo, hi),
272 })
273}
274
275fn parse_opt_generics(cx: &mut ParseCtxt) -> ParseResult<Generics> {
276 if !cx.peek(LAngle) {
277 let hi = cx.hi();
278 return Ok(Generics { params: vec![], predicates: None, span: cx.mk_span(hi, hi) });
279 }
280 let lo = cx.lo();
281 let params = angle(cx, Comma, parse_generic_param)?;
282 let hi = cx.hi();
283 Ok(Generics { params, predicates: None, span: cx.mk_span(lo, hi) })
284}
285
286fn parse_generic_param(cx: &mut ParseCtxt) -> ParseResult<GenericParam> {
287 let name = parse_ident(cx)?;
288 let mut kind = GenericParamKind::Type;
289 if cx.advance_if(Tok::As) {
290 let mut lookahead = cx.lookahead1();
291 if lookahead.advance_if("type") {
292 kind = GenericParamKind::Type;
293 } else if lookahead.advance_if("base") {
294 kind = GenericParamKind::Base;
295 } else {
296 return Err(lookahead.into_error());
297 }
298 };
299 Ok(GenericParam { name, kind, node_id: cx.next_node_id() })
300}
301
302fn invalid_ident_err(ident: &Ident) -> ParseError {
303 ParseError { kind: crate::ParseErrorKind::InvalidBinding, span: ident.span }
304}
305
306fn mut_as_strg(inputs: Vec<FnInput>, ensures: &[Ensures]) -> ParseResult<Vec<FnInput>> {
307 let locs = ensures
309 .iter()
310 .filter_map(|ens| if let Ensures::Type(ident, _, _) = ens { Some(ident) } else { None })
311 .collect::<HashSet<_>>();
312 let mut res = vec![];
314 for input in inputs {
315 if let FnInput::Ty(Some(ident), _, _) = &input
316 && locs.contains(&ident)
317 {
318 let FnInput::Ty(Some(ident), ty, id) = input else {
320 return Err(invalid_ident_err(ident));
321 };
322 let TyKind::Ref(Mutability::Mut, inner_ty) = ty.kind else {
323 return Err(invalid_ident_err(&ident));
324 };
325 res.push(FnInput::StrgRef(ident, *inner_ty, id));
326 } else {
327 res.push(input);
329 }
330 }
331 Ok(res)
332}
333
334pub(crate) fn parse_fn_sig(cx: &mut ParseCtxt) -> ParseResult<FnSig> {
342 let lo = cx.lo();
343 let asyncness = parse_asyncness(cx);
344 cx.expect(Tok::Fn)?;
345 let ident = if cx.peek(AnyIdent) { Some(parse_ident(cx)?) } else { None };
346 let mut generics = parse_opt_generics(cx)?;
347 let params = if cx.peek(OpenDelim(Bracket)) {
348 brackets(cx, Comma, |cx| parse_refine_param(cx, false))?
349 } else {
350 vec![]
351 };
352 let inputs = parens(cx, Comma, parse_fn_input)?;
353 let returns = parse_fn_ret(cx)?;
354 let requires = parse_opt_requires(cx)?;
355 let ensures = parse_opt_ensures(cx)?;
356 let inputs = mut_as_strg(inputs, &ensures)?;
357 generics.predicates = parse_opt_where(cx)?;
358 cx.expect(Tok::Eof)?;
359 let hi = cx.hi();
360 Ok(FnSig {
361 asyncness,
362 generics,
363 params,
364 ident,
365 inputs,
366 requires,
367 output: FnOutput { returns, ensures, node_id: cx.next_node_id() },
368 node_id: cx.next_node_id(),
369 span: cx.mk_span(lo, hi),
370 })
371}
372
373fn parse_opt_requires(cx: &mut ParseCtxt) -> ParseResult<Vec<Requires>> {
377 if !cx.advance_if(Tok::Requires) {
378 return Ok(vec![]);
379 }
380 punctuated_until(cx, Comma, [Tok::Ensures, Tok::Where, Tok::Eof], parse_requires_clause)
381}
382
383fn parse_requires_clause(cx: &mut ParseCtxt) -> ParseResult<Requires> {
387 let mut params = vec![];
388 if cx.advance_if(Tok::Forall) {
389 params = sep1(cx, Comma, |cx| parse_refine_param(cx, false))?;
390 cx.expect(Tok::Dot)?;
391 }
392 let pred = parse_expr(cx, true)?;
393 Ok(Requires { params, pred })
394}
395
396fn parse_opt_ensures(cx: &mut ParseCtxt) -> ParseResult<Vec<Ensures>> {
400 if !cx.advance_if(Tok::Ensures) {
401 return Ok(vec![]);
402 }
403 punctuated_until(cx, Comma, [Tok::Where, Tok::Eof], parse_ensures_clause)
404}
405
406fn parse_ensures_clause(cx: &mut ParseCtxt) -> ParseResult<Ensures> {
411 if cx.peek2(AnyIdent, Tok::Colon) {
412 let ident = parse_ident(cx)?;
414 cx.expect(Tok::Colon)?;
415 let ty = parse_type(cx)?;
416 Ok(Ensures::Type(ident, ty, cx.next_node_id()))
417 } else {
418 Ok(Ensures::Pred(parse_expr(cx, true)?))
420 }
421}
422
423fn parse_opt_where(cx: &mut ParseCtxt) -> ParseResult<Option<Vec<WhereBoundPredicate>>> {
424 if !cx.advance_if(Tok::Where) {
425 return Ok(None);
426 }
427 Ok(Some(punctuated_until(cx, Comma, Tok::Eof, parse_where_bound)?))
428}
429
430fn parse_where_bound(cx: &mut ParseCtxt) -> ParseResult<WhereBoundPredicate> {
431 let lo = cx.lo();
432 let bounded_ty = parse_type(cx)?;
433 cx.expect(Tok::Colon)?;
434 let bounds = parse_generic_bounds(cx)?;
435 let hi = cx.hi();
436 Ok(WhereBoundPredicate { span: cx.mk_span(lo, hi), bounded_ty, bounds })
437}
438
439fn parse_fn_ret(cx: &mut ParseCtxt) -> ParseResult<FnRetTy> {
443 if cx.advance_if(Tok::RArrow) {
444 Ok(FnRetTy::Ty(parse_type(cx)?))
445 } else {
446 let hi = cx.hi();
447 Ok(FnRetTy::Default(cx.mk_span(hi, hi)))
448 }
449}
450
451fn parse_fn_input(cx: &mut ParseCtxt) -> ParseResult<FnInput> {
458 if cx.peek2(AnyIdent, Tok::Colon) {
459 let bind = parse_ident(cx)?;
460 cx.expect(Tok::Colon)?;
461 if cx.advance_if2(Tok::And, Tok::Strg) {
462 Ok(FnInput::StrgRef(bind, parse_type(cx)?, cx.next_node_id()))
464 } else if cx.peek(AnyIdent) {
465 let path = parse_path(cx)?;
466 if cx.peek3(OpenDelim(Brace), AnyIdent, Tok::Colon) {
467 let bty = path_to_bty(path);
469 let ty = parse_bty_exists(cx, bty)?;
470 Ok(FnInput::Ty(Some(bind), ty, cx.next_node_id()))
471 } else if cx.peek(OpenDelim(Brace)) {
472 let pred = delimited(cx, Brace, |cx| parse_expr(cx, true))?;
474 Ok(FnInput::Constr(bind, path, pred, cx.next_node_id()))
475 } else {
476 let bty = path_to_bty(path);
478 let ty = parse_bty_rhs(cx, bty)?;
479 Ok(FnInput::Ty(Some(bind), ty, cx.next_node_id()))
480 }
481 } else {
482 Ok(FnInput::Ty(Some(bind), parse_type(cx)?, cx.next_node_id()))
484 }
485 } else {
486 Ok(FnInput::Ty(None, parse_type(cx)?, cx.next_node_id()))
488 }
489}
490
491fn parse_asyncness(cx: &mut ParseCtxt) -> Async {
495 let lo = cx.lo();
496 if cx.advance_if(Tok::Async) {
497 Async::Yes { node_id: cx.next_node_id(), span: cx.mk_span(lo, cx.hi()) }
498 } else {
499 Async::No
500 }
501}
502
503pub(crate) fn parse_type(cx: &mut ParseCtxt) -> ParseResult<Ty> {
519 let lo = cx.lo();
520 let mut lookahead = cx.lookahead1();
521 let kind = if lookahead.advance_if(Tok::Underscore) {
522 TyKind::Hole
523 } else if lookahead.advance_if(OpenDelim(Parenthesis)) {
524 let (mut tys, trailing) =
526 punctuated_with_trailing(cx, Comma, CloseDelim(Parenthesis), parse_type)?;
527 cx.expect(CloseDelim(Parenthesis))?;
528 if tys.len() == 1 && !trailing {
529 return Ok(tys.remove(0));
530 } else {
531 TyKind::Tuple(tys)
532 }
533 } else if lookahead.peek(OpenDelim(Brace)) {
534 delimited(cx, Brace, |cx| {
535 if cx.peek2(AnyIdent, [Tok::Comma, Tok::Dot, Tok::Colon]) {
536 parse_general_exists(cx)
538 } else {
539 let ty = parse_type(cx)?;
541 cx.expect(Tok::Caret)?;
542 let pred = parse_block_expr(cx)?;
543 Ok(TyKind::Constr(pred, Box::new(ty)))
544 }
545 })?
546 } else if lookahead.advance_if(Tok::And) {
547 let mutbl = if cx.advance_if(Tok::Mut) { Mutability::Mut } else { Mutability::Not };
549 TyKind::Ref(mutbl, Box::new(parse_type(cx)?))
550 } else if lookahead.advance_if(OpenDelim(Bracket)) {
551 let ty = parse_type(cx)?;
552 if cx.advance_if(Tok::Semi) {
553 let len = parse_const_arg(cx)?;
555 cx.expect(CloseDelim(Bracket))?;
556 TyKind::Array(Box::new(ty), len)
557 } else {
558 cx.expect(CloseDelim(Bracket))?;
560 let span = cx.mk_span(lo, cx.hi());
561 let kind = BaseTyKind::Slice(Box::new(ty));
562 return parse_bty_rhs(cx, BaseTy { kind, span });
563 }
564 } else if lookahead.advance_if(Tok::Impl) {
565 TyKind::ImplTrait(cx.next_node_id(), parse_generic_bounds(cx)?)
567 } else if lookahead.peek(AnyIdent) {
568 let path = parse_path(cx)?;
570 let bty = path_to_bty(path);
571 return parse_bty_rhs(cx, bty);
572 } else if lookahead.peek(LAngle) {
573 let bty = parse_qpath(cx)?;
575 return parse_bty_rhs(cx, bty);
576 } else {
577 return Err(lookahead.into_error());
578 };
579 let hi = cx.hi();
580 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
581}
582
583fn parse_qpath(cx: &mut ParseCtxt) -> ParseResult<BaseTy> {
587 let lo = cx.lo();
588 cx.expect(LAngle)?;
589 let qself = parse_type(cx)?;
590 cx.expect(Tok::As)?;
591 let mut segments = parse_segments(cx)?;
592 cx.expect(RAngle)?;
593 cx.expect(Tok::PathSep)?;
594 segments.extend(parse_segments(cx)?);
595 let hi = cx.hi();
596
597 let span = cx.mk_span(lo, hi);
598 let path = Path { segments, refine: vec![], node_id: cx.next_node_id(), span };
599 let kind = BaseTyKind::Path(Some(Box::new(qself)), path);
600 Ok(BaseTy { kind, span })
601}
602
603fn parse_general_exists(cx: &mut ParseCtxt) -> ParseResult<TyKind> {
607 let params = sep1(cx, Comma, |cx| parse_refine_param(cx, false))?;
608 cx.expect(Tok::Dot)?;
609 let ty = parse_type(cx)?;
610 let pred = if cx.advance_if(Tok::Caret) { Some(parse_block_expr(cx)?) } else { None };
611 Ok(TyKind::GeneralExists { params, ty: Box::new(ty), pred })
612}
613
614fn parse_bty_rhs(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
620 let lo = bty.span.lo();
621 if cx.peek(OpenDelim(Bracket)) {
622 let indices = parse_indices(cx)?;
624 let hi = cx.hi();
625 let kind = TyKind::Indexed { bty, indices };
626 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
627 } else if cx.peek(OpenDelim(Brace)) {
628 parse_bty_exists(cx, bty)
630 } else {
631 let hi = cx.hi();
633 let kind = TyKind::Base(bty);
634 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
635 }
636}
637
638fn parse_bty_exists(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
642 let lo = bty.span.lo();
643 delimited(cx, Brace, |cx| {
644 let bind = parse_ident(cx)?;
645 cx.expect(Tok::Colon)?;
646 let pred = parse_block_expr(cx)?;
647 let hi = cx.hi();
648 let kind = TyKind::Exists { bind, bty, pred };
649 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
650 })
651}
652
653fn path_to_bty(path: Path) -> BaseTy {
654 let span = path.span;
655 BaseTy { kind: BaseTyKind::Path(None, path), span }
656}
657
658fn parse_indices(cx: &mut ParseCtxt) -> ParseResult<Indices> {
659 let lo = cx.lo();
660 let indices = brackets(cx, Comma, parse_refine_arg)?;
661 let hi = cx.hi();
662 Ok(Indices { indices, span: cx.mk_span(lo, hi) })
663}
664
665fn parse_fn_bound_input(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
666 let lo = cx.lo();
667 let tys = parens(cx, Comma, parse_type)?;
668 let hi = cx.hi();
669 let kind = TyKind::Tuple(tys);
670 let span = cx.mk_span(lo, hi);
671 let in_ty = Ty { kind, node_id: cx.next_node_id(), span };
672 Ok(GenericArg { kind: GenericArgKind::Type(in_ty), node_id: cx.next_node_id() })
673}
674
675fn parse_fn_bound_output(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
676 let lo = cx.lo();
677
678 let ty = if cx.advance_if(Tok::RArrow) {
679 parse_type(cx)?
680 } else {
681 Ty { kind: TyKind::Tuple(vec![]), node_id: cx.next_node_id(), span: cx.mk_span(lo, lo) }
682 };
683 let hi = cx.hi();
684 let ident = Ident { name: Output, span: cx.mk_span(lo, hi) };
685 Ok(GenericArg { kind: GenericArgKind::Constraint(ident, ty), node_id: cx.next_node_id() })
686}
687
688fn parse_fn_bound_path(cx: &mut ParseCtxt) -> ParseResult<Path> {
689 let lo = cx.lo();
690 let ident = parse_ident(cx)?;
691 let in_arg = parse_fn_bound_input(cx)?;
692 let out_arg = parse_fn_bound_output(cx)?;
693 let args = vec![in_arg, out_arg];
694 let segment = PathSegment { ident, args, node_id: cx.next_node_id() };
695 let hi = cx.hi();
696 Ok(Path {
697 segments: vec![segment],
698 refine: vec![],
699 node_id: cx.next_node_id(),
700 span: cx.mk_span(lo, hi),
701 })
702}
703
704fn parse_generic_bounds(cx: &mut ParseCtxt) -> ParseResult<GenericBounds> {
705 let is_fn = cx.peek(["FnOnce", "FnMut", "Fn"]);
706 let path = if is_fn { parse_fn_bound_path(cx)? } else { parse_path(cx)? };
707 Ok(vec![TraitRef { path, node_id: cx.next_node_id() }])
708}
709
710fn parse_const_arg(cx: &mut ParseCtxt) -> ParseResult<ConstArg> {
711 let lo = cx.lo();
712 let mut lookahead = cx.lookahead1();
713 let kind = if lookahead.peek(AnyLit) {
714 let len = parse_int(cx)?;
715 ConstArgKind::Lit(len)
716 } else if lookahead.advance_if(Tok::Underscore) {
717 ConstArgKind::Infer
718 } else {
719 return Err(lookahead.into_error());
720 };
721 let hi = cx.hi();
722 Ok(ConstArg { kind, span: cx.mk_span(lo, hi) })
723}
724
725fn parse_path(cx: &mut ParseCtxt) -> ParseResult<Path> {
729 let lo = cx.lo();
730 let segments = parse_segments(cx)?;
731 let refine =
732 if cx.peek(OpenDelim(Parenthesis)) { parens(cx, Comma, parse_refine_arg)? } else { vec![] };
733 let hi = cx.hi();
734 Ok(Path { segments, refine, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
735}
736
737fn parse_segments(cx: &mut ParseCtxt) -> ParseResult<Vec<PathSegment>> {
741 sep1(cx, Tok::PathSep, parse_segment)
742}
743
744fn parse_segment(cx: &mut ParseCtxt) -> ParseResult<PathSegment> {
748 let ident = parse_ident(cx)?;
749 let args = opt_angle(cx, Comma, parse_generic_arg)?;
750 Ok(PathSegment { ident, node_id: cx.next_node_id(), args })
751}
752
753fn parse_generic_arg(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
757 let kind = if cx.peek2(AnyIdent, Tok::Eq) {
758 let ident = parse_ident(cx)?;
759 cx.expect(Tok::Eq)?;
760 let ty = parse_type(cx)?;
761 GenericArgKind::Constraint(ident, ty)
762 } else {
763 GenericArgKind::Type(parse_type(cx)?)
764 };
765 Ok(GenericArg { kind, node_id: cx.next_node_id() })
766}
767
768fn parse_refine_arg(cx: &mut ParseCtxt) -> ParseResult<RefineArg> {
775 let lo = cx.lo();
776 let arg = if cx.advance_if(Tok::At) {
777 let bind = parse_ident(cx)?;
779 let hi = cx.hi();
780 RefineArg::Bind(bind, BindKind::At, cx.mk_span(lo, hi), cx.next_node_id())
781 } else if cx.advance_if(Tok::Pound) {
782 let bind = parse_ident(cx)?;
784 let hi = cx.hi();
785 RefineArg::Bind(bind, BindKind::Pound, cx.mk_span(lo, hi), cx.next_node_id())
786 } else if cx.advance_if(Caret) {
787 let params = punctuated_until(cx, Comma, Caret, |cx| parse_refine_param(cx, false))?;
788 cx.expect(Caret)?;
789 let body = parse_expr(cx, true)?;
790 let hi = cx.hi();
791 RefineArg::Abs(params, body, cx.mk_span(lo, hi), cx.next_node_id())
792 } else {
793 RefineArg::Expr(parse_expr(cx, true)?)
795 };
796 Ok(arg)
797}
798
799fn parse_refine_param(cx: &mut ParseCtxt, require_sort: bool) -> ParseResult<RefineParam> {
804 let lo = cx.lo();
805 let mode = parse_opt_param_mode(cx);
806 let ident = parse_ident(cx)?;
807 let sort = if require_sort {
808 cx.expect(Tok::Colon)?;
809 parse_sort(cx)?
810 } else if cx.advance_if(Tok::Colon) {
811 parse_sort(cx)?
812 } else {
813 Sort::Infer
814 };
815 let hi = cx.hi();
816 Ok(RefineParam { mode, ident, sort, span: cx.mk_span(lo, hi), node_id: cx.next_node_id() })
817}
818
819fn parse_opt_param_mode(cx: &mut ParseCtxt) -> Option<ParamMode> {
823 if cx.advance_if(Tok::Hrn) {
824 Some(ParamMode::Horn)
825 } else if cx.advance_if(Tok::Hdl) {
826 Some(ParamMode::Hindley)
827 } else {
828 None
829 }
830}
831
832pub(crate) fn parse_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
833 parse_binops(cx, Precedence::MIN, allow_struct)
834}
835
836fn parse_binops(cx: &mut ParseCtxt, base: Precedence, allow_struct: bool) -> ParseResult<Expr> {
837 let mut lhs = unary_expr(cx, allow_struct)?;
838 loop {
839 let lo = cx.lo();
840 let Some((op, ntokens)) = cx.peek_binop() else { break };
841 let precedence = Precedence::of_binop(&op);
842 if precedence < base {
843 break;
844 }
845 cx.advance_by(ntokens);
846 let next = match precedence.associativity() {
847 Associativity::Right => precedence,
848 Associativity::Left => precedence.next(),
849 Associativity::None => {
850 if let ExprKind::BinaryOp(op, ..) = &lhs.kind {
851 if Precedence::of_binop(op) == precedence {
852 return Err(cx.cannot_be_chained(lo, cx.hi()));
853 }
854 }
855 precedence.next()
856 }
857 };
858 let rhs = parse_binops(cx, next, allow_struct)?;
859 let span = lhs.span.to(rhs.span);
860 lhs = Expr {
861 kind: ExprKind::BinaryOp(op, Box::new([lhs, rhs])),
862 node_id: cx.next_node_id(),
863 span,
864 }
865 }
866 Ok(lhs)
867}
868
869fn unary_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
873 let lo = cx.lo();
874 let kind = if cx.advance_if(Tok::Minus) {
875 ExprKind::UnaryOp(UnOp::Neg, Box::new(unary_expr(cx, allow_struct)?))
876 } else if cx.advance_if(Tok::Not) {
877 ExprKind::UnaryOp(UnOp::Not, Box::new(unary_expr(cx, allow_struct)?))
878 } else {
879 return parse_trailer_expr(cx, allow_struct);
880 };
881 let hi = cx.hi();
882 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
883}
884
885fn parse_trailer_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
891 let lo = cx.lo();
892 let mut e = parse_atom(cx, allow_struct)?;
893 loop {
894 let kind = if cx.advance_if(Tok::Dot) {
895 let field = parse_ident(cx)?;
897 ExprKind::Dot(Box::new(e), field)
898 } else if cx.peek(OpenDelim(Parenthesis)) {
899 let args = parens(cx, Comma, |cx| parse_expr(cx, true))?;
901 ExprKind::Call(Box::new(e), args)
902 } else {
903 break;
904 };
905 let hi = cx.hi();
906 e = Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) };
907 }
908 Ok(e)
909}
910
911fn parse_atom(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
922 let lo = cx.lo();
923 let mut lookahead = cx.lookahead1();
924 if lookahead.peek(Tok::If) {
925 parse_if_expr(cx)
927 } else if lookahead.peek(AnyLit) {
928 parse_lit(cx)
930 } else if lookahead.peek(OpenDelim(Parenthesis)) {
931 delimited(cx, Parenthesis, |cx| parse_expr(cx, true))
932 } else if lookahead.peek(AnyIdent) {
933 let path = parse_expr_path(cx)?;
934 let kind = if allow_struct && cx.peek(Tok::OpenDelim(Brace)) {
935 let args = braces(cx, Comma, parse_constructor_arg)?;
937 ExprKind::Constructor(Some(path), args)
938 } else {
939 ExprKind::Path(path)
941 };
942 let hi = cx.hi();
943 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
944 } else if allow_struct && lookahead.peek(OpenDelim(Brace)) {
945 let args = braces(cx, Comma, parse_constructor_arg)?;
947 let hi = cx.hi();
948 Ok(Expr {
949 kind: ExprKind::Constructor(None, args),
950 node_id: cx.next_node_id(),
951 span: cx.mk_span(lo, hi),
952 })
953 } else if lookahead.advance_if(LAngle) {
954 let lo = cx.lo();
956 let qself = parse_type(cx)?;
957 cx.expect(Tok::As)?;
958 let path = parse_path(cx)?;
959 cx.expect(RAngle)?;
960 cx.expect(Tok::PathSep)?;
961 let name = parse_ident(cx)?;
962 let hi = cx.hi();
963 let kind = ExprKind::AssocReft(Box::new(qself), path, name);
964 return Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) });
965 } else if lookahead.peek([Tok::Exists, Tok::Forall]) {
966 parse_bounded_quantifier(cx)
967 } else {
968 Err(lookahead.into_error())
969 }
970}
971
972fn parse_bounded_quantifier(cx: &mut ParseCtxt) -> ParseResult<Expr> {
977 let lo = cx.lo();
978 let mut lookahead = cx.lookahead1();
979 let quant = if lookahead.advance_if(Tok::Forall) {
980 QuantKind::Forall
981 } else if lookahead.advance_if(Tok::Exists) {
982 QuantKind::Exists
983 } else {
984 return Err(lookahead.into_error());
985 };
986 let param = parse_refine_param(cx, false)?;
987 cx.expect(Tok::In)?;
988 let start = parse_int(cx)?;
989 cx.expect(Tok::DotDot)?;
990 let end = parse_int(cx)?;
991 let body = parse_block(cx)?;
992 let hi = cx.hi();
993 Ok(Expr {
994 kind: ExprKind::BoundedQuant(quant, param, start..end, Box::new(body)),
995 node_id: cx.next_node_id(),
996 span: cx.mk_span(lo, hi),
997 })
998}
999
1000fn parse_constructor_arg(cx: &mut ParseCtxt) -> ParseResult<ConstructorArg> {
1004 let lo = cx.lo();
1005 let mut lookahead = cx.lookahead1();
1006 if lookahead.peek(AnyIdent) {
1007 let ident = parse_ident(cx)?;
1008 cx.expect(Tok::Colon)?;
1009 let expr = parse_expr(cx, true)?;
1010 let hi = cx.hi();
1011 Ok(ConstructorArg::FieldExpr(FieldExpr {
1012 ident,
1013 expr,
1014 node_id: cx.next_node_id(),
1015 span: cx.mk_span(lo, hi),
1016 }))
1017 } else if lookahead.advance_if(Tok::DotDot) {
1018 let spread = parse_expr(cx, true)?;
1019 let hi = cx.hi();
1020 Ok(ConstructorArg::Spread(Spread {
1021 expr: spread,
1022 node_id: cx.next_node_id(),
1023 span: cx.mk_span(lo, hi),
1024 }))
1025 } else {
1026 Err(lookahead.into_error())
1027 }
1028}
1029
1030fn parse_expr_path(cx: &mut ParseCtxt) -> ParseResult<ExprPath> {
1032 let lo = cx.lo();
1033 let segments = sep1(cx, Tok::PathSep, parse_expr_path_segment)?;
1034 let hi = cx.hi();
1035 Ok(ExprPath { segments, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1036}
1037
1038fn parse_expr_path_segment(cx: &mut ParseCtxt) -> ParseResult<ExprPathSegment> {
1039 Ok(ExprPathSegment { ident: parse_ident(cx)?, node_id: cx.next_node_id() })
1040}
1041
1042fn parse_if_expr(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1046 let mut branches = vec![];
1047
1048 loop {
1049 let lo = cx.lo();
1050 cx.expect(Tok::If)?;
1051 let cond = parse_expr(cx, false)?;
1052 let then_ = parse_block(cx)?;
1053 branches.push((lo, cond, then_));
1054 cx.expect(Tok::Else)?;
1055
1056 if !cx.peek(Tok::If) {
1057 break;
1058 }
1059 }
1060 let mut else_ = parse_block(cx)?;
1061
1062 let hi = cx.hi();
1063 while let Some((lo, cond, then_)) = branches.pop() {
1064 else_ = Expr {
1065 kind: ExprKind::IfThenElse(Box::new([cond, then_, else_])),
1066 node_id: cx.next_node_id(),
1067 span: cx.mk_span(lo, hi),
1068 };
1069 }
1070 Ok(else_)
1071}
1072
1073fn parse_block_expr(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1075 let lo = cx.lo();
1076 let decls = repeat_while(cx, Tok::Let, parse_let_decl)?;
1077 let body = parse_expr(cx, true)?;
1078 let hi = cx.hi();
1079
1080 if decls.is_empty() {
1081 Ok(body)
1082 } else {
1083 let kind = ExprKind::Block(decls, Box::new(body));
1084 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1085 }
1086}
1087
1088fn parse_let_decl(cx: &mut ParseCtxt) -> ParseResult<LetDecl> {
1090 cx.expect(Tok::Let)?;
1091 let param = parse_refine_param(cx, false)?;
1092 cx.expect(Tok::Eq)?;
1093 let init = parse_expr(cx, true)?;
1094 cx.expect(Tok::Semi)?;
1095 Ok(LetDecl { param, init })
1096}
1097
1098fn parse_block(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1100 delimited(cx, Brace, parse_block_expr)
1101}
1102
1103fn parse_lit(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1107 if let (lo, Tok::Literal(lit), hi) = cx.at(0) {
1108 cx.advance();
1109 Ok(Expr {
1110 kind: ExprKind::Literal(lit),
1111 node_id: cx.next_node_id(),
1112 span: cx.mk_span(lo, hi),
1113 })
1114 } else {
1115 Err(cx.unexpected_token(AnyLit.display().collect()))
1116 }
1117}
1118
1119fn parse_ident(cx: &mut ParseCtxt) -> ParseResult<Ident> {
1120 if let (lo, Tok::Ident(name), hi) = cx.at(0) {
1121 cx.advance();
1122 Ok(Ident { name, span: cx.mk_span(lo, hi) })
1123 } else {
1124 Err(cx.unexpected_token(AnyIdent.display().collect()))
1125 }
1126}
1127
1128fn parse_int<T: FromStr>(cx: &mut ParseCtxt) -> ParseResult<T> {
1129 if let Tok::Literal(lit) = cx.at(0).1 {
1130 if let LitKind::Integer = lit.kind {
1131 if let Ok(value) = lit.symbol.as_str().parse::<T>() {
1132 cx.advance();
1133 return Ok(value);
1134 }
1135 }
1136 }
1137 Err(cx.unexpected_token(vec![std::any::type_name::<T>()]))
1138}
1139
1140fn parse_sort(cx: &mut ParseCtxt) -> ParseResult<Sort> {
1146 if cx.peek(OpenDelim(Parenthesis)) {
1147 let inputs = parens(cx, Comma, parse_base_sort)?;
1149 cx.expect(Tok::RArrow)?;
1150 let output = parse_base_sort(cx)?;
1151 Ok(Sort::Func { inputs, output })
1152 } else {
1153 let bsort = parse_base_sort(cx)?;
1154 if cx.advance_if(Tok::RArrow) {
1155 let output = parse_base_sort(cx)?;
1157 Ok(Sort::Func { inputs: vec![bsort], output })
1158 } else {
1159 Ok(Sort::Base(bsort))
1161 }
1162 }
1163}
1164
1165fn parse_base_sort(cx: &mut ParseCtxt) -> ParseResult<BaseSort> {
1172 if cx.advance_if(Tok::BitVec) {
1173 cx.expect(LAngle)?;
1175 let len = parse_int(cx)?;
1176 cx.expect(RAngle)?;
1177 Ok(BaseSort::BitVec(len))
1178 } else if cx.advance_if(LAngle) {
1179 let qself = parse_type(cx)?;
1181 cx.expect(Tok::As)?;
1182 let mut path = parse_path(cx)?;
1183 cx.expect(RAngle)?;
1184 cx.expect(Tok::PathSep)?;
1185 path.segments.push(parse_segment(cx)?);
1186 Ok(BaseSort::SortOf(Box::new(qself), path))
1187 } else {
1188 let segments = sep1(cx, Tok::PathSep, parse_ident)?;
1190 let args = opt_angle(cx, Comma, parse_base_sort)?;
1191 let path = SortPath { segments, args, node_id: cx.next_node_id() };
1192 Ok(BaseSort::Path(path))
1193 }
1194}
1195
1196#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
1198enum Precedence {
1199 Iff,
1201 Implies,
1203 Or,
1205 And,
1207 Compare,
1209 BitOr,
1211 BitXor,
1213 BitAnd,
1215 Shift,
1217 Sum,
1219 Product,
1221 Prefix,
1223}
1224
1225enum Associativity {
1226 Right,
1227 Left,
1228 None,
1229}
1230
1231impl Precedence {
1232 const MIN: Self = Precedence::Iff;
1233
1234 fn of_binop(op: &BinOp) -> Precedence {
1235 match op {
1236 BinOp::Iff => Precedence::Iff,
1237 BinOp::Imp => Precedence::Implies,
1238 BinOp::Or => Precedence::Or,
1239 BinOp::And => Precedence::And,
1240 BinOp::Eq | BinOp::Ne | BinOp::Gt | BinOp::Ge | BinOp::Lt | BinOp::Le => {
1241 Precedence::Compare
1242 }
1243 BinOp::BitOr => Precedence::BitOr,
1244 BinOp::BitAnd => Precedence::BitAnd,
1245 BinOp::BitShl | BinOp::BitShr => Precedence::Shift,
1246 BinOp::Add | BinOp::Sub => Precedence::Sum,
1247 BinOp::Mul | BinOp::Div | BinOp::Mod => Precedence::Product,
1248 }
1249 }
1250
1251 fn next(self) -> Precedence {
1252 match self {
1253 Precedence::Iff => Precedence::Implies,
1254 Precedence::Implies => Precedence::Or,
1255 Precedence::Or => Precedence::And,
1256 Precedence::And => Precedence::Compare,
1257 Precedence::Compare => Precedence::BitOr,
1258 Precedence::BitOr => Precedence::BitXor,
1259 Precedence::BitXor => Precedence::BitAnd,
1260 Precedence::BitAnd => Precedence::Shift,
1261 Precedence::Shift => Precedence::Sum,
1262 Precedence::Sum => Precedence::Product,
1263 Precedence::Product => Precedence::Prefix,
1264 Precedence::Prefix => Precedence::Prefix,
1265 }
1266 }
1267
1268 fn associativity(self) -> Associativity {
1269 match self {
1270 Precedence::Or
1271 | Precedence::And
1272 | Precedence::BitOr
1273 | Precedence::BitXor
1274 | Precedence::BitAnd
1275 | Precedence::Shift
1276 | Precedence::Sum
1277 | Precedence::Product => Associativity::Left,
1278 Precedence::Compare | Precedence::Iff => Associativity::None,
1279 Precedence::Implies | Precedence::Prefix => Associativity::Right,
1280 }
1281 }
1282}