1pub(crate) mod lookahead;
2mod utils;
3use std::{collections::HashSet, str::FromStr, vec};
4
5use lookahead::{AnyLit, LAngle, NonReserved, 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,
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, QuantKind, RefineArg, RefineParam,
24 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}
54
55#[derive(Default)]
56struct ParsedAttrs {
57 normal: Vec<Attr>,
58 syntax: Vec<SyntaxAttr>,
59}
60
61impl ParsedAttrs {
62 fn is_reft(&self) -> bool {
63 self.syntax
64 .iter()
65 .any(|attr| matches!(attr, SyntaxAttr::Reft))
66 }
67
68 fn is_hide(&self) -> bool {
69 self.syntax
70 .iter()
71 .any(|attr| matches!(attr, SyntaxAttr::Hide))
72 }
73
74 fn refined_by(&mut self) -> Option<RefineParams> {
75 let pos = self
76 .syntax
77 .iter()
78 .position(|x| matches!(x, SyntaxAttr::RefinedBy(_)))?;
79 if let SyntaxAttr::RefinedBy(params) = self.syntax.remove(pos) {
80 Some(params)
81 } else {
82 None
83 }
84 }
85
86 fn invariant(&mut self) -> Option<Expr> {
87 let pos = self
88 .syntax
89 .iter()
90 .position(|x| matches!(x, SyntaxAttr::Invariant(_)))?;
91 if let SyntaxAttr::Invariant(exp) = self.syntax.remove(pos) { Some(exp) } else { None }
92 }
93}
94
95pub(crate) fn parse_yes_or_no_with_reason(cx: &mut ParseCtxt) -> ParseResult<bool> {
101 let mut lookahead = cx.lookahead1();
102 if lookahead.advance_if(sym::yes) {
103 if cx.advance_if(token::Comma) {
104 parse_reason(cx)?;
105 }
106 Ok(true)
107 } else if lookahead.advance_if(sym::no) {
108 if cx.advance_if(token::Comma) {
109 parse_reason(cx)?;
110 }
111 Ok(false)
112 } else if lookahead.peek(sym::reason) {
113 parse_reason(cx)?;
114 Ok(true)
115 } else {
116 Err(lookahead.into_error())
117 }
118}
119
120fn parse_reason(cx: &mut ParseCtxt) -> ParseResult {
124 cx.expect(sym::reason)?;
125 cx.expect(token::Eq)?;
126 cx.expect(AnyLit)
127}
128
129pub(crate) fn parse_ident_list(cx: &mut ParseCtxt) -> ParseResult<Vec<Ident>> {
133 punctuated_until(cx, Comma, token::Eof, parse_ident)
134}
135
136pub(crate) fn parse_flux_items(cx: &mut ParseCtxt) -> ParseResult<Vec<FluxItem>> {
140 until(cx, token::Eof, parse_flux_item)
141}
142
143fn parse_flux_item(cx: &mut ParseCtxt) -> ParseResult<FluxItem> {
150 let mut lookahead = cx.lookahead1();
151 if lookahead.peek(token::Pound) || lookahead.peek(kw::Fn) {
152 parse_reft_func(cx).map(FluxItem::FuncDef)
153 } else if lookahead.peek(kw::Local) || lookahead.peek(kw::Qualifier) {
154 parse_qualifier(cx).map(FluxItem::Qualifier)
155 } else if lookahead.peek(kw::Opaque) {
156 parse_sort_decl(cx).map(FluxItem::SortDecl)
157 } else if lookahead.peek(kw::Property) {
158 parse_primop_property(cx).map(FluxItem::PrimOpProp)
159 } else {
160 Err(lookahead.into_error())
161 }
162}
163
164pub(crate) fn parse_detached_specs(cx: &mut ParseCtxt) -> ParseResult<surface::DetachedSpecs> {
168 let items = until(cx, token::Eof, parse_detached_item)?;
169 Ok(surface::DetachedSpecs { items })
170}
171
172pub(crate) fn parse_detached_item(cx: &mut ParseCtxt) -> ParseResult<DetachedItem> {
180 let attrs = parse_attrs(cx)?;
181 let mut lookahead = cx.lookahead1();
182 if lookahead.peek(kw::Fn) {
183 Ok(parse_detached_fn_sig(cx, attrs)?.map_kind(DetachedItemKind::FnSig))
184 } else if lookahead.peek(kw::Mod) {
185 parse_detached_mod(cx)
186 } else if lookahead.peek(kw::Struct) {
187 parse_detached_struct(cx, attrs)
188 } else if lookahead.peek(kw::Enum) {
189 parse_detached_enum(cx, attrs)
190 } else if lookahead.peek(kw::Impl) {
191 parse_detached_impl(cx, attrs)
192 } else if lookahead.peek(kw::Trait) {
193 parse_detached_trait(cx, attrs)
194 } else {
195 Err(lookahead.into_error())
196 }
197}
198
199fn parse_detached_field(cx: &mut ParseCtxt) -> ParseResult<(Ident, Ty)> {
203 let ident = parse_ident(cx)?;
204 cx.expect(token::Colon)?;
205 let ty = parse_type(cx)?;
206 Ok((ident, ty))
207}
208
209fn parse_detached_enum(cx: &mut ParseCtxt, mut attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
213 cx.expect(kw::Enum)?;
214 let path = parse_expr_path(cx)?;
215 let generics = Some(parse_opt_generics(cx)?);
216 let refined_by = attrs.refined_by();
217 let invariants = attrs.invariant().into_iter().collect();
218 let variants = braces(cx, Comma, |cx| parse_variant(cx, true))?
219 .into_iter()
220 .map(Some)
221 .collect();
222 let enum_def = EnumDef { generics, refined_by, variants, invariants, reflected: false };
223 Ok(DetachedItem {
224 attrs: attrs.normal,
225 path,
226 kind: DetachedItemKind::Enum(enum_def),
227 node_id: cx.next_node_id(),
228 })
229}
230
231fn parse_detached_struct(cx: &mut ParseCtxt, mut attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
232 cx.expect(kw::Struct)?;
233 let path = parse_expr_path(cx)?;
234 let generics = Some(parse_opt_generics(cx)?);
235 let refined_by = attrs.refined_by();
236 let invariants = attrs.invariant().into_iter().collect();
237 let fields = if cx.peek(token::OpenBrace) {
238 braces(cx, Comma, parse_detached_field)?
239 .into_iter()
240 .map(|(_, ty)| Some(ty))
241 .collect()
242 } else {
243 vec![]
244 };
245 let struct_def = StructDef { generics, opaque: false, refined_by, invariants, fields };
246 Ok(DetachedItem {
247 attrs: attrs.normal,
248 path,
249 kind: DetachedItemKind::Struct(struct_def),
250 node_id: cx.next_node_id(),
251 })
252}
253
254fn ident_path(cx: &mut ParseCtxt, ident: Ident) -> ExprPath {
255 let span = ident.span;
256 let segments = vec![ExprPathSegment { ident, node_id: cx.next_node_id() }];
257 ExprPath { segments, span, node_id: cx.next_node_id() }
258}
259
260fn parse_detached_fn_sig(
261 cx: &mut ParseCtxt,
262 attrs: ParsedAttrs,
263) -> ParseResult<DetachedItem<FnSig>> {
264 let fn_sig = parse_fn_sig(cx, token::Semi)?;
265 let span = fn_sig.span;
266 let ident = fn_sig
267 .ident
268 .ok_or(ParseError { kind: crate::ParseErrorKind::InvalidDetachedSpec, span })?;
269 let path = ident_path(cx, ident);
270 Ok(DetachedItem { attrs: attrs.normal, path, kind: fn_sig, node_id: cx.next_node_id() })
271}
272
273fn parse_detached_mod(cx: &mut ParseCtxt) -> ParseResult<DetachedItem> {
277 cx.expect(kw::Mod)?;
278 let path = parse_expr_path(cx)?;
279 cx.expect(TokenKind::open_delim(Brace))?;
280 let items = until(cx, TokenKind::close_delim(Brace), parse_detached_item)?;
281 cx.expect(TokenKind::close_delim(Brace))?;
282 Ok(DetachedItem {
283 attrs: vec![],
284 path,
285 kind: DetachedItemKind::Mod(DetachedSpecs { items }),
286 node_id: cx.next_node_id(),
287 })
288}
289
290fn parse_detached_trait(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
294 cx.expect(kw::Trait)?;
295 let path = parse_expr_path(cx)?;
296 let _generics = parse_opt_generics(cx)?;
297 cx.expect(TokenKind::open_delim(Brace))?;
298
299 let mut items = vec![];
300 let mut refts = vec![];
301 while !cx.peek(TokenKind::close_delim(Brace)) {
302 let assoc_item_attrs = parse_attrs(cx)?;
303 if assoc_item_attrs.is_reft() {
304 refts.push(parse_trait_assoc_reft(cx)?);
305 } else {
306 items.push(parse_detached_fn_sig(cx, assoc_item_attrs)?);
307 }
308 }
309 cx.expect(TokenKind::close_delim(Brace))?;
310 Ok(DetachedItem {
311 attrs: attrs.normal,
312 path,
313 kind: DetachedItemKind::Trait(DetachedTrait { items, refts }),
314 node_id: cx.next_node_id(),
315 })
316}
317
318fn parse_detached_impl(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
322 let lo = cx.lo();
323 cx.expect(kw::Impl)?;
324 let hi = cx.hi();
325 let span = cx.mk_span(lo, hi);
326 let outer_path = parse_expr_path(cx)?;
327 let _generics = parse_opt_generics(cx)?;
328 let inner_path = if cx.advance_if(kw::For) {
329 let path = parse_expr_path(cx)?;
330 let _generics = parse_opt_generics(cx)?;
331 Some(path)
332 } else {
333 None
334 };
335 cx.expect(TokenKind::open_delim(Brace))?;
336
337 let mut items = vec![];
338 let mut refts = vec![];
339 while !cx.peek(TokenKind::close_delim(Brace)) {
340 let assoc_item_attrs = parse_attrs(cx)?;
342 if assoc_item_attrs.is_reft() && inner_path.is_some() {
343 refts.push(parse_impl_assoc_reft(cx)?);
344 } else {
345 items.push(parse_detached_fn_sig(cx, assoc_item_attrs)?);
346 }
347 }
348 cx.expect(TokenKind::close_delim(Brace))?;
349 if let Some(path) = inner_path {
350 Ok(DetachedItem {
351 attrs: attrs.normal,
352 path,
353 kind: DetachedItemKind::TraitImpl(DetachedTraitImpl {
354 trait_: outer_path,
355 items,
356 refts,
357 span,
358 }),
359 node_id: cx.next_node_id(),
360 })
361 } else {
362 Ok(DetachedItem {
363 attrs: attrs.normal,
364 path: outer_path,
365 kind: DetachedItemKind::InherentImpl(DetachedInherentImpl { items, span }),
366 node_id: cx.next_node_id(),
367 })
368 }
369}
370
371fn parse_attr(cx: &mut ParseCtxt, attrs: &mut ParsedAttrs) -> ParseResult {
372 cx.expect(token::Pound)?;
373 cx.expect(token::OpenBracket)?;
374 let mut lookahead = cx.lookahead1();
375 if lookahead.advance_if(kw::Trusted) {
376 if cx.advance_if(token::OpenParen) {
377 parse_reason(cx)?;
378 cx.expect(token::CloseParen)?;
379 }
380 attrs.normal.push(Attr::Trusted(Trusted::Yes));
381 } else if lookahead.advance_if(sym::hide) {
382 attrs.syntax.push(SyntaxAttr::Hide);
383 } else if lookahead.advance_if(kw::Reft) {
384 attrs.syntax.push(SyntaxAttr::Reft);
385 } else if lookahead.advance_if(kw::RefinedBy) {
386 attrs
387 .syntax
388 .push(SyntaxAttr::RefinedBy(delimited(cx, Parenthesis, parse_refined_by)?));
389 } else if lookahead.advance_if(kw::Invariant) {
390 attrs
391 .syntax
392 .push(SyntaxAttr::Invariant(delimited(cx, Parenthesis, |cx| parse_expr(cx, true))?));
393 } else {
394 return Err(lookahead.into_error());
395 };
396 cx.expect(token::CloseBracket)
397}
398
399fn parse_attrs(cx: &mut ParseCtxt) -> ParseResult<ParsedAttrs> {
400 let mut attrs = ParsedAttrs::default();
401 repeat_while(cx, token::Pound, |cx| parse_attr(cx, &mut attrs))?;
402 Ok(attrs)
403}
404
405fn parse_reft_func(cx: &mut ParseCtxt) -> ParseResult<SpecFunc> {
413 let attrs = parse_attrs(cx)?;
414 let hide = attrs.is_hide();
415 cx.expect(kw::Fn)?;
416 let name = parse_ident(cx)?;
417 let sort_vars = opt_angle(cx, Comma, parse_ident)?;
418 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
419 cx.expect(token::RArrow)?;
420 let output = parse_sort(cx)?;
421 let body = if cx.peek(token::OpenBrace) {
422 Some(parse_block(cx)?)
423 } else {
424 cx.expect(token::Semi)?;
425 None
426 };
427 Ok(SpecFunc { name, sort_vars, params, output, body, hide })
428}
429
430fn parse_qualifier(cx: &mut ParseCtxt) -> ParseResult<Qualifier> {
436 let lo = cx.lo();
437 let local = cx.advance_if(kw::Local);
438 cx.expect(kw::Qualifier)?;
439 let name = parse_ident(cx)?;
440 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
441 let expr = parse_block(cx)?;
442 let hi = cx.hi();
443 Ok(Qualifier { global: !local, name, params, expr, span: cx.mk_span(lo, hi) })
444}
445
446fn parse_sort_decl(cx: &mut ParseCtxt) -> ParseResult<SortDecl> {
450 cx.expect(kw::Opaque)?;
451 cx.expect(kw::Sort)?;
452 let name = parse_ident(cx)?;
453 cx.expect(token::Semi)?;
454 Ok(SortDecl { name })
455}
456
457fn parse_binop(cx: &mut ParseCtxt) -> ParseResult<BinOp> {
459 let (op, ntokens) = cx
460 .peek_binop()
461 .ok_or_else(|| cx.unexpected_token(vec![Expected::Str("binary operator")]))?;
462 cx.advance_by(ntokens);
463 Ok(op)
464}
465
466fn parse_primop_property(cx: &mut ParseCtxt) -> ParseResult<PrimOpProp> {
470 let lo = cx.lo();
471 cx.expect(kw::Property)?;
472
473 let name = parse_ident(cx)?;
475
476 cx.expect(token::OpenBracket)?;
478 let op = parse_binop(cx)?;
479 cx.expect(token::CloseBracket)?;
480
481 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::No))?;
483
484 let body = parse_block(cx)?;
485 let hi = cx.hi();
486
487 Ok(PrimOpProp { name, op, params, body, span: cx.mk_span(lo, hi) })
488}
489
490pub(crate) fn parse_trait_assoc_refts(cx: &mut ParseCtxt) -> ParseResult<Vec<TraitAssocReft>> {
491 until(cx, token::Eof, parse_trait_assoc_reft)
492}
493
494fn parse_trait_assoc_reft(cx: &mut ParseCtxt) -> ParseResult<TraitAssocReft> {
500 let lo = cx.lo();
501 let final_ = cx.advance_if(kw::Final);
502 cx.expect(kw::Fn)?;
503 let name = parse_ident(cx)?;
504 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
505 cx.expect(token::RArrow)?;
506 let output = parse_base_sort(cx)?;
507 let body = if cx.peek(token::OpenBrace) {
508 Some(parse_block(cx)?)
509 } else {
510 cx.advance_if(token::Semi);
511 None
512 };
513 let hi = cx.hi();
514 Ok(TraitAssocReft { name, params, output, body, span: cx.mk_span(lo, hi), final_ })
515}
516
517pub(crate) fn parse_impl_assoc_refts(cx: &mut ParseCtxt) -> ParseResult<Vec<ImplAssocReft>> {
518 until(cx, token::Eof, parse_impl_assoc_reft)
519}
520
521fn parse_impl_assoc_reft(cx: &mut ParseCtxt) -> ParseResult<ImplAssocReft> {
525 let lo = cx.lo();
526 cx.expect(kw::Fn)?;
527 let name = parse_ident(cx)?;
528 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
529 cx.expect(token::RArrow)?;
530 let output = parse_base_sort(cx)?;
531 let body = parse_block(cx)?;
532 let hi = cx.hi();
533 Ok(ImplAssocReft { name, params, output, body, span: cx.mk_span(lo, hi) })
534}
535
536pub(crate) fn parse_refined_by(cx: &mut ParseCtxt) -> ParseResult<RefineParams> {
540 punctuated_until(cx, Comma, token::Eof, |cx| parse_refine_param(cx, RequireSort::Yes))
541}
542
543pub(crate) fn parse_variant(cx: &mut ParseCtxt, ret_arrow: bool) -> ParseResult<VariantDef> {
549 let lo = cx.lo();
550 let mut fields = vec![];
551 let mut ret = None;
552 let ident = if ret_arrow || cx.peek2(NonReserved, token::OpenParen) {
553 Some(parse_ident(cx)?)
554 } else {
555 None
556 };
557 if cx.peek(token::OpenParen) || cx.peek(token::OpenBrace) {
558 fields = parse_fields(cx)?;
559 if cx.advance_if(token::RArrow) {
560 ret = Some(parse_variant_ret(cx)?);
561 }
562 } else {
563 if ret_arrow {
564 cx.expect(token::RArrow)?;
565 }
566 ret = Some(parse_variant_ret(cx)?);
567 };
568 let hi = cx.hi();
569 Ok(VariantDef { ident, fields, ret, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
570}
571
572fn parse_fields(cx: &mut ParseCtxt) -> ParseResult<Vec<Ty>> {
576 let mut lookahead = cx.lookahead1();
577 if lookahead.peek(token::OpenParen) {
578 parens(cx, Comma, parse_type)
579 } else if lookahead.peek(token::OpenBrace) {
580 braces(cx, Comma, parse_type)
581 } else {
582 Err(lookahead.into_error())
583 }
584}
585
586fn parse_variant_ret(cx: &mut ParseCtxt) -> ParseResult<VariantRet> {
590 let path = parse_path(cx)?;
591 let indices = if cx.peek(token::OpenBracket) {
592 parse_indices(cx)?
593 } else {
594 let hi = cx.hi();
595 Indices { indices: vec![], span: cx.mk_span(hi, hi) }
596 };
597 Ok(VariantRet { path, indices })
598}
599
600pub(crate) fn parse_type_alias(cx: &mut ParseCtxt) -> ParseResult<TyAlias> {
601 let lo = cx.lo();
602 cx.expect(kw::Type)?;
603 let ident = parse_ident(cx)?;
604 let generics = parse_opt_generics(cx)?;
605 let params = if cx.peek(token::OpenParen) {
606 parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?
607 } else {
608 vec![]
609 };
610 let index = if cx.peek(token::OpenBracket) {
611 Some(delimited(cx, Bracket, |cx| parse_refine_param(cx, RequireSort::Yes))?)
612 } else {
613 None
614 };
615 cx.expect(token::Eq)?;
616 let ty = parse_type(cx)?;
617 let hi = cx.hi();
618 Ok(TyAlias {
619 ident,
620 generics,
621 params,
622 index,
623 ty,
624 node_id: cx.next_node_id(),
625 span: cx.mk_span(lo, hi),
626 })
627}
628
629fn parse_opt_generics(cx: &mut ParseCtxt) -> ParseResult<Generics> {
630 if !cx.peek(LAngle) {
631 let hi = cx.hi();
632 return Ok(Generics { params: vec![], predicates: None, span: cx.mk_span(hi, hi) });
633 }
634 let lo = cx.lo();
635 let params = angle(cx, Comma, parse_generic_param)?;
636 let hi = cx.hi();
637 Ok(Generics { params, predicates: None, span: cx.mk_span(lo, hi) })
638}
639
640fn parse_generic_param(cx: &mut ParseCtxt) -> ParseResult<GenericParam> {
641 let name = parse_ident(cx)?;
642 Ok(GenericParam { name, node_id: cx.next_node_id() })
643}
644
645fn invalid_ident_err(ident: &Ident) -> ParseError {
646 ParseError { kind: crate::ParseErrorKind::InvalidBinding, span: ident.span }
647}
648
649fn mut_as_strg(inputs: Vec<FnInput>, ensures: &[Ensures]) -> ParseResult<Vec<FnInput>> {
650 let locs = ensures
652 .iter()
653 .filter_map(|ens| if let Ensures::Type(ident, _, _) = ens { Some(ident) } else { None })
654 .collect::<HashSet<_>>();
655 let mut res = vec![];
657 for input in inputs {
658 if let FnInput::Ty(Some(ident), _, _) = &input
659 && locs.contains(&ident)
660 {
661 let FnInput::Ty(Some(ident), ty, id) = input else {
663 return Err(invalid_ident_err(ident));
664 };
665 let TyKind::Ref(Mutability::Mut, inner_ty) = ty.kind else {
666 return Err(invalid_ident_err(&ident));
667 };
668 res.push(FnInput::StrgRef(ident, *inner_ty, id));
669 } else {
670 res.push(input);
672 }
673 }
674 Ok(res)
675}
676
677pub(crate) fn parse_fn_sig<T: PeekExpected>(cx: &mut ParseCtxt, end: T) -> ParseResult<FnSig> {
685 let lo = cx.lo();
686 let asyncness = parse_asyncness(cx);
687 cx.expect(kw::Fn)?;
688 let ident = if cx.peek(NonReserved) { Some(parse_ident(cx)?) } else { None };
689 let mut generics = parse_opt_generics(cx)?;
690 let params = if cx.peek(token::OpenBracket) {
691 brackets(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?
692 } else {
693 vec![]
694 };
695 let inputs = parens(cx, Comma, parse_fn_input)?;
696 let returns = parse_fn_ret(cx)?;
697 let requires = parse_opt_requires(cx)?;
698 let ensures = parse_opt_ensures(cx)?;
699 let inputs = mut_as_strg(inputs, &ensures)?;
700 generics.predicates = parse_opt_where(cx)?;
701 cx.expect(end)?;
702 let hi = cx.hi();
703 Ok(FnSig {
704 asyncness,
705 generics,
706 params,
707 ident,
708 inputs,
709 requires,
710 output: FnOutput { returns, ensures, node_id: cx.next_node_id() },
711 node_id: cx.next_node_id(),
712 span: cx.mk_span(lo, hi),
713 })
714}
715
716fn parse_opt_requires(cx: &mut ParseCtxt) -> ParseResult<Vec<Requires>> {
720 if !cx.advance_if(kw::Requires) {
721 return Ok(vec![]);
722 }
723 punctuated_until(
724 cx,
725 Comma,
726 |t: TokenKind| t.is_keyword(kw::Ensures) || t.is_keyword(kw::Where) || t.is_eof(),
727 parse_requires_clause,
728 )
729}
730
731fn parse_requires_clause(cx: &mut ParseCtxt) -> ParseResult<Requires> {
735 let mut params = vec![];
736 if cx.advance_if(kw::Forall) {
737 params = sep1(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
738 cx.expect(token::Dot)?;
739 }
740 let pred = parse_expr(cx, true)?;
741 Ok(Requires { params, pred })
742}
743
744fn parse_opt_ensures(cx: &mut ParseCtxt) -> ParseResult<Vec<Ensures>> {
748 if !cx.advance_if(kw::Ensures) {
749 return Ok(vec![]);
750 }
751 punctuated_until(
752 cx,
753 Comma,
754 |t: TokenKind| t.is_keyword(kw::Where) || t.is_eof(),
755 parse_ensures_clause,
756 )
757}
758
759fn parse_ensures_clause(cx: &mut ParseCtxt) -> ParseResult<Ensures> {
764 if cx.peek2(NonReserved, token::Colon) {
765 let ident = parse_ident(cx)?;
767 cx.expect(token::Colon)?;
768 let ty = parse_type(cx)?;
769 Ok(Ensures::Type(ident, ty, cx.next_node_id()))
770 } else {
771 Ok(Ensures::Pred(parse_expr(cx, true)?))
773 }
774}
775
776fn parse_opt_where(cx: &mut ParseCtxt) -> ParseResult<Option<Vec<WhereBoundPredicate>>> {
777 if !cx.advance_if(kw::Where) {
778 return Ok(None);
779 }
780 Ok(Some(punctuated_until(cx, Comma, token::Eof, parse_where_bound)?))
781}
782
783fn parse_where_bound(cx: &mut ParseCtxt) -> ParseResult<WhereBoundPredicate> {
784 let lo = cx.lo();
785 let bounded_ty = parse_type(cx)?;
786 cx.expect(token::Colon)?;
787 let bounds = parse_generic_bounds(cx)?;
788 let hi = cx.hi();
789 Ok(WhereBoundPredicate { span: cx.mk_span(lo, hi), bounded_ty, bounds })
790}
791
792fn parse_fn_ret(cx: &mut ParseCtxt) -> ParseResult<FnRetTy> {
796 if cx.advance_if(token::RArrow) {
797 Ok(FnRetTy::Ty(Box::new(parse_type(cx)?)))
798 } else {
799 let hi = cx.hi();
800 Ok(FnRetTy::Default(cx.mk_span(hi, hi)))
801 }
802}
803
804fn parse_fn_input(cx: &mut ParseCtxt) -> ParseResult<FnInput> {
811 if cx.peek2(NonReserved, token::Colon) {
812 let bind = parse_ident(cx)?;
813 cx.expect(token::Colon)?;
814 if cx.advance_if2(token::And, kw::Strg) {
815 Ok(FnInput::StrgRef(bind, parse_type(cx)?, cx.next_node_id()))
817 } else if cx.peek(NonReserved) {
818 let path = parse_path(cx)?;
819 if cx.peek3(token::OpenBrace, NonReserved, token::Colon) {
820 let bty = path_to_bty(path);
822 let ty = parse_bty_exists(cx, bty)?;
823 Ok(FnInput::Ty(Some(bind), ty, cx.next_node_id()))
824 } else if cx.peek(token::OpenBrace) {
825 let pred = delimited(cx, Brace, |cx| parse_expr(cx, true))?;
827 Ok(FnInput::Constr(bind, path, pred, cx.next_node_id()))
828 } else {
829 let bty = path_to_bty(path);
831 let ty = parse_bty_rhs(cx, bty)?;
832 Ok(FnInput::Ty(Some(bind), ty, cx.next_node_id()))
833 }
834 } else {
835 Ok(FnInput::Ty(Some(bind), parse_type(cx)?, cx.next_node_id()))
837 }
838 } else {
839 Ok(FnInput::Ty(None, parse_type(cx)?, cx.next_node_id()))
841 }
842}
843
844fn parse_asyncness(cx: &mut ParseCtxt) -> Async {
848 let lo = cx.lo();
849 if cx.advance_if(kw::Async) {
850 Async::Yes { node_id: cx.next_node_id(), span: cx.mk_span(lo, cx.hi()) }
851 } else {
852 Async::No
853 }
854}
855
856pub(crate) fn parse_type(cx: &mut ParseCtxt) -> ParseResult<Ty> {
872 let lo = cx.lo();
873 let mut lookahead = cx.lookahead1();
874 let kind = if lookahead.advance_if(kw::Underscore) {
875 TyKind::Hole
876 } else if lookahead.advance_if(token::OpenParen) {
877 let (mut tys, trailing) =
879 punctuated_with_trailing(cx, Comma, token::CloseParen, parse_type)?;
880 cx.expect(token::CloseParen)?;
881 if tys.len() == 1 && !trailing {
882 return Ok(tys.remove(0));
883 } else {
884 TyKind::Tuple(tys)
885 }
886 } else if lookahead.peek(token::OpenBrace) {
887 delimited(cx, Brace, |cx| {
888 if cx.peek2(NonReserved, AnyOf([token::Comma, token::Dot, token::Colon])) {
889 parse_general_exists(cx)
891 } else {
892 let ty = parse_type(cx)?;
894 cx.expect(token::Or)?;
895 let pred = parse_block_expr(cx)?;
896 Ok(TyKind::Constr(pred, Box::new(ty)))
897 }
898 })?
899 } else if lookahead.advance_if(token::And) {
900 let mutbl = if cx.advance_if(kw::Mut) { Mutability::Mut } else { Mutability::Not };
902 TyKind::Ref(mutbl, Box::new(parse_type(cx)?))
903 } else if lookahead.advance_if(token::OpenBracket) {
904 let ty = parse_type(cx)?;
905 if cx.advance_if(token::Semi) {
906 let len = parse_const_arg(cx)?;
908 cx.expect(token::CloseBracket)?;
909 TyKind::Array(Box::new(ty), len)
910 } else {
911 cx.expect(token::CloseBracket)?;
913 let span = cx.mk_span(lo, cx.hi());
914 let kind = BaseTyKind::Slice(Box::new(ty));
915 return parse_bty_rhs(cx, BaseTy { kind, span });
916 }
917 } else if lookahead.advance_if(kw::Impl) {
918 TyKind::ImplTrait(cx.next_node_id(), parse_generic_bounds(cx)?)
920 } else if lookahead.peek(NonReserved) {
921 let path = parse_path(cx)?;
923 let bty = path_to_bty(path);
924 return parse_bty_rhs(cx, bty);
925 } else if lookahead.peek(LAngle) {
926 let bty = parse_qpath(cx)?;
928 return parse_bty_rhs(cx, bty);
929 } else {
930 return Err(lookahead.into_error());
931 };
932 let hi = cx.hi();
933 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
934}
935
936fn parse_qpath(cx: &mut ParseCtxt) -> ParseResult<BaseTy> {
940 let lo = cx.lo();
941 cx.expect(LAngle)?;
942 let qself = parse_type(cx)?;
943 cx.expect(kw::As)?;
944 let mut segments = parse_segments(cx)?;
945 cx.expect(RAngle)?;
946 cx.expect(token::PathSep)?;
947 segments.extend(parse_segments(cx)?);
948 let hi = cx.hi();
949
950 let span = cx.mk_span(lo, hi);
951 let path = Path { segments, refine: vec![], node_id: cx.next_node_id(), span };
952 let kind = BaseTyKind::Path(Some(Box::new(qself)), path);
953 Ok(BaseTy { kind, span })
954}
955
956fn parse_general_exists(cx: &mut ParseCtxt) -> ParseResult<TyKind> {
960 let params = sep1(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
961 cx.expect(token::Dot)?;
962 let ty = parse_type(cx)?;
963 let pred = if cx.advance_if(token::Or) { Some(parse_block_expr(cx)?) } else { None };
964 Ok(TyKind::GeneralExists { params, ty: Box::new(ty), pred })
965}
966
967fn parse_bty_rhs(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
973 let lo = bty.span.lo();
974 if cx.peek(token::OpenBracket) {
975 let indices = parse_indices(cx)?;
977 let hi = cx.hi();
978 let kind = TyKind::Indexed { bty, indices };
979 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
980 } else if cx.peek(token::OpenBrace) {
981 parse_bty_exists(cx, bty)
983 } else {
984 let hi = cx.hi();
986 let kind = TyKind::Base(bty);
987 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
988 }
989}
990
991fn parse_bty_exists(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
995 let lo = bty.span.lo();
996 delimited(cx, Brace, |cx| {
997 let bind = parse_ident(cx)?;
998 cx.expect(token::Colon)?;
999 let pred = parse_block_expr(cx)?;
1000 let hi = cx.hi();
1001 let kind = TyKind::Exists { bind, bty, pred };
1002 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1003 })
1004}
1005
1006fn path_to_bty(path: Path) -> BaseTy {
1007 let span = path.span;
1008 BaseTy { kind: BaseTyKind::Path(None, path), span }
1009}
1010
1011fn parse_indices(cx: &mut ParseCtxt) -> ParseResult<Indices> {
1012 let lo = cx.lo();
1013 let indices = brackets(cx, Comma, parse_refine_arg)?;
1014 let hi = cx.hi();
1015 Ok(Indices { indices, span: cx.mk_span(lo, hi) })
1016}
1017
1018fn parse_fn_bound_input(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1019 let lo = cx.lo();
1020 let tys = parens(cx, Comma, parse_type)?;
1021 let hi = cx.hi();
1022 let kind = TyKind::Tuple(tys);
1023 let span = cx.mk_span(lo, hi);
1024 let in_ty = Ty { kind, node_id: cx.next_node_id(), span };
1025 Ok(GenericArg { kind: GenericArgKind::Type(in_ty), node_id: cx.next_node_id() })
1026}
1027
1028fn parse_fn_bound_output(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1029 let lo = cx.lo();
1030
1031 let ty = if cx.advance_if(token::RArrow) {
1032 parse_type(cx)?
1033 } else {
1034 Ty { kind: TyKind::Tuple(vec![]), node_id: cx.next_node_id(), span: cx.mk_span(lo, lo) }
1035 };
1036 let hi = cx.hi();
1037 let ident = Ident { name: Output, span: cx.mk_span(lo, hi) };
1038 Ok(GenericArg { kind: GenericArgKind::Constraint(ident, ty), node_id: cx.next_node_id() })
1039}
1040
1041fn parse_fn_bound_path(cx: &mut ParseCtxt) -> ParseResult<Path> {
1042 let lo = cx.lo();
1043 let ident = parse_ident(cx)?;
1044 let in_arg = parse_fn_bound_input(cx)?;
1045 let out_arg = parse_fn_bound_output(cx)?;
1046 let args = vec![in_arg, out_arg];
1047 let segment = PathSegment { ident, args, node_id: cx.next_node_id() };
1048 let hi = cx.hi();
1049 Ok(Path {
1050 segments: vec![segment],
1051 refine: vec![],
1052 node_id: cx.next_node_id(),
1053 span: cx.mk_span(lo, hi),
1054 })
1055}
1056
1057fn parse_generic_bounds(cx: &mut ParseCtxt) -> ParseResult<GenericBounds> {
1058 let path = if cx.peek(sym::FnOnce) || cx.peek(sym::FnMut) || cx.peek(sym::Fn) {
1059 parse_fn_bound_path(cx)?
1060 } else {
1061 parse_path(cx)?
1062 };
1063 Ok(vec![TraitRef { path, node_id: cx.next_node_id() }])
1064}
1065
1066fn parse_const_arg(cx: &mut ParseCtxt) -> ParseResult<ConstArg> {
1067 let lo = cx.lo();
1068 let mut lookahead = cx.lookahead1();
1069 let kind = if lookahead.peek(AnyLit) {
1070 let len = parse_int(cx)?;
1071 ConstArgKind::Lit(len)
1072 } else if lookahead.advance_if(kw::Underscore) {
1073 ConstArgKind::Infer
1074 } else {
1075 return Err(lookahead.into_error());
1076 };
1077 let hi = cx.hi();
1078 Ok(ConstArg { kind, span: cx.mk_span(lo, hi) })
1079}
1080
1081fn parse_path(cx: &mut ParseCtxt) -> ParseResult<Path> {
1085 let lo = cx.lo();
1086 let segments = parse_segments(cx)?;
1087 let refine =
1088 if cx.peek(token::OpenParen) { parens(cx, Comma, parse_refine_arg)? } else { vec![] };
1089 let hi = cx.hi();
1090 Ok(Path { segments, refine, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1091}
1092
1093fn parse_segments(cx: &mut ParseCtxt) -> ParseResult<Vec<PathSegment>> {
1097 sep1(cx, token::PathSep, parse_segment)
1098}
1099
1100fn parse_segment(cx: &mut ParseCtxt) -> ParseResult<PathSegment> {
1104 let ident = parse_ident(cx)?;
1105 let args = opt_angle(cx, Comma, parse_generic_arg)?;
1106 Ok(PathSegment { ident, node_id: cx.next_node_id(), args })
1107}
1108
1109fn parse_generic_arg(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1113 let kind = if cx.peek2(NonReserved, token::Eq) {
1114 let ident = parse_ident(cx)?;
1115 cx.expect(token::Eq)?;
1116 let ty = parse_type(cx)?;
1117 GenericArgKind::Constraint(ident, ty)
1118 } else {
1119 GenericArgKind::Type(parse_type(cx)?)
1120 };
1121 Ok(GenericArg { kind, node_id: cx.next_node_id() })
1122}
1123
1124fn parse_refine_arg(cx: &mut ParseCtxt) -> ParseResult<RefineArg> {
1131 let lo = cx.lo();
1132 let arg = if cx.advance_if(token::At) {
1133 let bind = parse_ident(cx)?;
1135 let hi = cx.hi();
1136 RefineArg::Bind(bind, BindKind::At, cx.mk_span(lo, hi), cx.next_node_id())
1137 } else if cx.advance_if(token::Pound) {
1138 let bind = parse_ident(cx)?;
1140 let hi = cx.hi();
1141 RefineArg::Bind(bind, BindKind::Pound, cx.mk_span(lo, hi), cx.next_node_id())
1142 } else if cx.advance_if(Or) {
1143 let params =
1144 punctuated_until(cx, Comma, Or, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
1145 cx.expect(Or)?;
1146 let body = parse_expr(cx, true)?;
1147 let hi = cx.hi();
1148 RefineArg::Abs(params, body, cx.mk_span(lo, hi), cx.next_node_id())
1149 } else {
1150 RefineArg::Expr(parse_expr(cx, true)?)
1152 };
1153 Ok(arg)
1154}
1155
1156enum RequireSort {
1158 Yes,
1160 Maybe,
1162 No,
1164}
1165
1166fn parse_sort_if_required(cx: &mut ParseCtxt, require_sort: RequireSort) -> ParseResult<Sort> {
1167 match require_sort {
1168 RequireSort::No => Ok(Sort::Infer),
1169 RequireSort::Maybe => {
1170 if cx.advance_if(token::Colon) {
1171 parse_sort(cx)
1172 } else {
1173 Ok(Sort::Infer)
1174 }
1175 }
1176 RequireSort::Yes => {
1177 cx.expect(token::Colon)?;
1178 parse_sort(cx)
1179 }
1180 }
1181}
1182
1183fn parse_refine_param(cx: &mut ParseCtxt, require_sort: RequireSort) -> ParseResult<RefineParam> {
1189 let lo = cx.lo();
1190 let mode = parse_opt_param_mode(cx);
1191 let ident = parse_ident(cx)?;
1192 let sort = parse_sort_if_required(cx, require_sort)?;
1193 let hi = cx.hi();
1194 Ok(RefineParam { mode, ident, sort, span: cx.mk_span(lo, hi), node_id: cx.next_node_id() })
1195}
1196
1197fn parse_opt_param_mode(cx: &mut ParseCtxt) -> Option<ParamMode> {
1201 if cx.advance_if(kw::Hrn) {
1202 Some(ParamMode::Horn)
1203 } else if cx.advance_if(kw::Hdl) {
1204 Some(ParamMode::Hindley)
1205 } else {
1206 None
1207 }
1208}
1209
1210pub(crate) fn parse_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1211 parse_binops(cx, Precedence::MIN, allow_struct)
1212}
1213
1214fn parse_binops(cx: &mut ParseCtxt, base: Precedence, allow_struct: bool) -> ParseResult<Expr> {
1215 let mut lhs = unary_expr(cx, allow_struct)?;
1216 loop {
1217 let lo = cx.lo();
1218 let Some((op, ntokens)) = cx.peek_binop() else { break };
1219 let precedence = Precedence::of_binop(&op);
1220 if precedence < base {
1221 break;
1222 }
1223 cx.advance_by(ntokens);
1224 let next = match precedence.associativity() {
1225 Associativity::Right => precedence,
1226 Associativity::Left => precedence.next(),
1227 Associativity::None => {
1228 if let ExprKind::BinaryOp(op, ..) = &lhs.kind
1229 && Precedence::of_binop(op) == precedence
1230 {
1231 return Err(cx.cannot_be_chained(lo, cx.hi()));
1232 }
1233 precedence.next()
1234 }
1235 };
1236 let rhs = parse_binops(cx, next, allow_struct)?;
1237 let span = lhs.span.to(rhs.span);
1238 lhs = Expr {
1239 kind: ExprKind::BinaryOp(op, Box::new([lhs, rhs])),
1240 node_id: cx.next_node_id(),
1241 span,
1242 }
1243 }
1244 Ok(lhs)
1245}
1246
1247fn unary_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1251 let lo = cx.lo();
1252 let kind = if cx.advance_if(token::Minus) {
1253 ExprKind::UnaryOp(UnOp::Neg, Box::new(unary_expr(cx, allow_struct)?))
1254 } else if cx.advance_if(token::Bang) {
1255 ExprKind::UnaryOp(UnOp::Not, Box::new(unary_expr(cx, allow_struct)?))
1256 } else {
1257 return parse_trailer_expr(cx, allow_struct);
1258 };
1259 let hi = cx.hi();
1260 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1261}
1262
1263fn parse_trailer_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1269 let lo = cx.lo();
1270 let mut e = parse_atom(cx, allow_struct)?;
1271 loop {
1272 let kind = if cx.advance_if(token::Dot) {
1273 let field = parse_ident(cx)?;
1275 ExprKind::Dot(Box::new(e), field)
1276 } else if cx.peek(token::OpenParen) {
1277 let args = parens(cx, Comma, |cx| parse_expr(cx, true))?;
1279 ExprKind::Call(Box::new(e), args)
1280 } else {
1281 break;
1282 };
1283 let hi = cx.hi();
1284 e = Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) };
1285 }
1286 Ok(e)
1287}
1288
1289fn parse_atom(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1301 let lo = cx.lo();
1302 let mut lookahead = cx.lookahead1();
1303 if lookahead.peek(kw::If) {
1304 parse_if_expr(cx)
1306 } else if lookahead.peek(AnyLit) {
1307 parse_lit(cx)
1309 } else if lookahead.peek(token::OpenParen) {
1310 delimited(cx, Parenthesis, |cx| parse_expr(cx, true))
1311 } else if lookahead.peek(NonReserved) {
1312 let path = parse_expr_path(cx)?;
1313 let kind = if allow_struct && cx.peek(token::OpenBrace) {
1314 let args = braces(cx, Comma, parse_constructor_arg)?;
1316 ExprKind::Constructor(Some(path), args)
1317 } else {
1318 ExprKind::Path(path)
1320 };
1321 let hi = cx.hi();
1322 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1323 } else if allow_struct && lookahead.peek(token::OpenBrace) {
1324 let args = braces(cx, Comma, parse_constructor_arg)?;
1326 let hi = cx.hi();
1327 Ok(Expr {
1328 kind: ExprKind::Constructor(None, args),
1329 node_id: cx.next_node_id(),
1330 span: cx.mk_span(lo, hi),
1331 })
1332 } else if lookahead.advance_if(LAngle) {
1333 let lo = cx.lo();
1335 let qself = parse_type(cx)?;
1336 cx.expect(kw::As)?;
1337 let path = parse_path(cx)?;
1338 cx.expect(RAngle)?;
1339 cx.expect(token::PathSep)?;
1340 let name = parse_ident(cx)?;
1341 let hi = cx.hi();
1342 let kind = ExprKind::AssocReft(Box::new(qself), path, name);
1343 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1344 } else if lookahead.peek(token::OpenBracket) {
1345 parse_prim_uif(cx)
1346 } else if lookahead.peek(kw::Exists) || lookahead.peek(kw::Forall) {
1347 parse_bounded_quantifier(cx)
1348 } else {
1349 Err(lookahead.into_error())
1350 }
1351}
1352
1353fn parse_prim_uif(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1354 let lo = cx.lo();
1355 cx.expect(token::OpenBracket)?;
1356 let op = parse_binop(cx)?;
1357 cx.expect(token::CloseBracket)?;
1358 let hi = cx.hi();
1359 Ok(Expr { kind: ExprKind::PrimUIF(op), node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1360}
1361
1362fn parse_bounded_quantifier(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1367 let lo = cx.lo();
1368 let mut lookahead = cx.lookahead1();
1369 let quant = if lookahead.advance_if(kw::Forall) {
1370 QuantKind::Forall
1371 } else if lookahead.advance_if(kw::Exists) {
1372 QuantKind::Exists
1373 } else {
1374 return Err(lookahead.into_error());
1375 };
1376 let param = parse_refine_param(cx, RequireSort::Maybe)?;
1377 cx.expect(kw::In)?;
1378 let start = parse_int(cx)?;
1379 cx.expect(token::DotDot)?;
1380 let end = parse_int(cx)?;
1381 let body = parse_block(cx)?;
1382 let hi = cx.hi();
1383 Ok(Expr {
1384 kind: ExprKind::BoundedQuant(quant, param, start..end, Box::new(body)),
1385 node_id: cx.next_node_id(),
1386 span: cx.mk_span(lo, hi),
1387 })
1388}
1389
1390fn parse_constructor_arg(cx: &mut ParseCtxt) -> ParseResult<ConstructorArg> {
1394 let lo = cx.lo();
1395 let mut lookahead = cx.lookahead1();
1396 if lookahead.peek(NonReserved) {
1397 let ident = parse_ident(cx)?;
1398 cx.expect(token::Colon)?;
1399 let expr = parse_expr(cx, true)?;
1400 let hi = cx.hi();
1401 Ok(ConstructorArg::FieldExpr(FieldExpr {
1402 ident,
1403 expr,
1404 node_id: cx.next_node_id(),
1405 span: cx.mk_span(lo, hi),
1406 }))
1407 } else if lookahead.advance_if(token::DotDot) {
1408 let spread = parse_expr(cx, true)?;
1409 let hi = cx.hi();
1410 Ok(ConstructorArg::Spread(Spread {
1411 expr: spread,
1412 node_id: cx.next_node_id(),
1413 span: cx.mk_span(lo, hi),
1414 }))
1415 } else {
1416 Err(lookahead.into_error())
1417 }
1418}
1419
1420fn parse_expr_path(cx: &mut ParseCtxt) -> ParseResult<ExprPath> {
1422 let lo = cx.lo();
1423 let segments = sep1(cx, token::PathSep, parse_expr_path_segment)?;
1424 let hi = cx.hi();
1425 Ok(ExprPath { segments, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1426}
1427
1428fn parse_expr_path_segment(cx: &mut ParseCtxt) -> ParseResult<ExprPathSegment> {
1429 Ok(ExprPathSegment { ident: parse_ident(cx)?, node_id: cx.next_node_id() })
1430}
1431
1432fn parse_if_expr(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1436 let mut branches = vec![];
1437
1438 loop {
1439 let lo = cx.lo();
1440 cx.expect(kw::If)?;
1441 let cond = parse_expr(cx, false)?;
1442 let then_ = parse_block(cx)?;
1443 branches.push((lo, cond, then_));
1444 cx.expect(kw::Else)?;
1445
1446 if !cx.peek(kw::If) {
1447 break;
1448 }
1449 }
1450 let mut else_ = parse_block(cx)?;
1451
1452 let hi = cx.hi();
1453 while let Some((lo, cond, then_)) = branches.pop() {
1454 else_ = Expr {
1455 kind: ExprKind::IfThenElse(Box::new([cond, then_, else_])),
1456 node_id: cx.next_node_id(),
1457 span: cx.mk_span(lo, hi),
1458 };
1459 }
1460 Ok(else_)
1461}
1462
1463fn parse_block(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1465 delimited(cx, Brace, parse_block_expr)
1466}
1467
1468fn parse_block_expr(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1470 let lo = cx.lo();
1471 let decls = repeat_while(cx, kw::Let, parse_let_decl)?;
1472 let body = parse_expr(cx, true)?;
1473 let hi = cx.hi();
1474
1475 if decls.is_empty() {
1476 Ok(body)
1477 } else {
1478 let kind = ExprKind::Block(decls, Box::new(body));
1479 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1480 }
1481}
1482
1483fn parse_let_decl(cx: &mut ParseCtxt) -> ParseResult<LetDecl> {
1485 cx.expect(kw::Let)?;
1486 let param = parse_refine_param(cx, RequireSort::Maybe)?;
1487 cx.expect(token::Eq)?;
1488 let init = parse_expr(cx, true)?;
1489 cx.expect(token::Semi)?;
1490 Ok(LetDecl { param, init })
1491}
1492
1493fn parse_lit(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1497 if let Token { kind: token::Literal(lit), lo, hi } = cx.at(0) {
1498 cx.advance();
1499 Ok(Expr {
1500 kind: ExprKind::Literal(lit),
1501 node_id: cx.next_node_id(),
1502 span: cx.mk_span(lo, hi),
1503 })
1504 } else {
1505 Err(cx.unexpected_token(vec![AnyLit.expected()]))
1506 }
1507}
1508
1509fn parse_ident(cx: &mut ParseCtxt) -> ParseResult<Ident> {
1510 if let Token { kind: token::Ident(name, is_raw), lo, hi } = cx.at(0)
1511 && (!cx.is_reserved(name) || is_raw == IdentIsRaw::Yes)
1512 {
1513 cx.advance();
1514 return Ok(Ident { name, span: cx.mk_span(lo, hi) });
1515 }
1516 Err(cx.unexpected_token(vec![NonReserved.expected()]))
1517}
1518
1519fn parse_int<T: FromStr>(cx: &mut ParseCtxt) -> ParseResult<T> {
1520 if let token::Literal(lit) = cx.at(0).kind
1521 && let LitKind::Integer = lit.kind
1522 && let Ok(value) = lit.symbol.as_str().parse::<T>()
1523 {
1524 cx.advance();
1525 return Ok(value);
1526 }
1527
1528 Err(cx.unexpected_token(vec![Expected::Str(std::any::type_name::<T>())]))
1529}
1530
1531fn parse_sort(cx: &mut ParseCtxt) -> ParseResult<Sort> {
1537 if cx.peek(token::OpenParen) {
1538 let inputs = parens(cx, Comma, parse_base_sort)?;
1540 cx.expect(token::RArrow)?;
1541 let output = parse_base_sort(cx)?;
1542 Ok(Sort::Func { inputs, output })
1543 } else {
1544 let bsort = parse_base_sort(cx)?;
1545 if cx.advance_if(token::RArrow) {
1546 let output = parse_base_sort(cx)?;
1548 Ok(Sort::Func { inputs: vec![bsort], output })
1549 } else {
1550 Ok(Sort::Base(bsort))
1552 }
1553 }
1554}
1555
1556fn parse_base_sort(cx: &mut ParseCtxt) -> ParseResult<BaseSort> {
1563 if cx.advance_if(kw::Bitvec) {
1564 cx.expect(LAngle)?;
1566 let len = parse_int(cx)?;
1567 cx.expect(RAngle)?;
1568 Ok(BaseSort::BitVec(len))
1569 } else if cx.advance_if(LAngle) {
1570 let qself = parse_type(cx)?;
1572 cx.expect(kw::As)?;
1573 let mut path = parse_path(cx)?;
1574 cx.expect(RAngle)?;
1575 cx.expect(token::PathSep)?;
1576 path.segments.push(parse_segment(cx)?);
1577 Ok(BaseSort::SortOf(Box::new(qself), path))
1578 } else {
1579 let segments = sep1(cx, token::PathSep, parse_ident)?;
1581 let args = opt_angle(cx, Comma, parse_base_sort)?;
1582 let path = SortPath { segments, args, node_id: cx.next_node_id() };
1583 Ok(BaseSort::Path(path))
1584 }
1585}
1586
1587#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
1589enum Precedence {
1590 Iff,
1592 Implies,
1594 Or,
1596 And,
1598 Compare,
1600 BitOr,
1602 BitXor,
1604 BitAnd,
1606 Shift,
1608 Sum,
1610 Product,
1612 Prefix,
1614}
1615
1616enum Associativity {
1617 Right,
1618 Left,
1619 None,
1620}
1621
1622impl Precedence {
1623 const MIN: Self = Precedence::Iff;
1624
1625 fn of_binop(op: &BinOp) -> Precedence {
1626 match op {
1627 BinOp::Iff => Precedence::Iff,
1628 BinOp::Imp => Precedence::Implies,
1629 BinOp::Or => Precedence::Or,
1630 BinOp::And => Precedence::And,
1631 BinOp::Eq | BinOp::Ne | BinOp::Gt | BinOp::Ge | BinOp::Lt | BinOp::Le => {
1632 Precedence::Compare
1633 }
1634 BinOp::BitOr => Precedence::BitOr,
1635 BinOp::BitXor => Precedence::BitXor,
1636 BinOp::BitAnd => Precedence::BitAnd,
1637 BinOp::BitShl | BinOp::BitShr => Precedence::Shift,
1638 BinOp::Add | BinOp::Sub => Precedence::Sum,
1639 BinOp::Mul | BinOp::Div | BinOp::Mod => Precedence::Product,
1640 }
1641 }
1642
1643 fn next(self) -> Precedence {
1644 match self {
1645 Precedence::Iff => Precedence::Implies,
1646 Precedence::Implies => Precedence::Or,
1647 Precedence::Or => Precedence::And,
1648 Precedence::And => Precedence::Compare,
1649 Precedence::Compare => Precedence::BitOr,
1650 Precedence::BitOr => Precedence::BitXor,
1651 Precedence::BitXor => Precedence::BitAnd,
1652 Precedence::BitAnd => Precedence::Shift,
1653 Precedence::Shift => Precedence::Sum,
1654 Precedence::Sum => Precedence::Product,
1655 Precedence::Product => Precedence::Prefix,
1656 Precedence::Prefix => Precedence::Prefix,
1657 }
1658 }
1659
1660 fn associativity(self) -> Associativity {
1661 match self {
1662 Precedence::Or
1663 | Precedence::And
1664 | Precedence::BitOr
1665 | Precedence::BitXor
1666 | Precedence::BitAnd
1667 | Precedence::Shift
1668 | Precedence::Sum
1669 | Precedence::Product => Associativity::Left,
1670 Precedence::Compare | Precedence::Iff => Associativity::None,
1671 Precedence::Implies | Precedence::Prefix => Associativity::Right,
1672 }
1673 }
1674}