1pub(crate) mod lookahead;
2mod utils;
3use std::{collections::HashSet, str::FromStr, vec};
4
5use lookahead::{AnyLit, LAngle, NonReserved, RAngle};
6use rustc_ast::token::Lit;
7use rustc_data_structures::unord::UnordSet;
8use rustc_span::{Symbol, sym::Output};
9use utils::{
10 angle, braces, brackets, delimited, opt_angle, parens, punctuated_until,
11 punctuated_with_trailing, repeat_while, sep1, until,
12};
13
14use crate::{
15 ParseCtxt, ParseError, ParseResult,
16 parser::lookahead::{AnyOf, Expected, PeekExpected},
17 surface::{
18 self, Async,
19 Attr::{self},
20 Axiom, BareFnTy, BaseSort, BaseTy, BaseTyKind, BinOp, BindKind, ConstArg, ConstArgKind,
21 ConstructorArg, DetachedInherentImpl, DetachedItem, DetachedItemKind, DetachedSpecs,
22 DetachedTrait, DetachedTraitImpl, Ensures, EnumDef, Expr, ExprKind, ExprPath,
23 ExprPathSegment, FieldExpr, FluxItem, FnInput, FnOutput, FnRetTy, FnSig, GenericArg,
24 GenericArgKind, GenericBounds, GenericParam, Generics, Ident, ImplAssocReft, Indices,
25 LetDecl, LitKind, Mutability, ParamMode, Path, PathSegment, PrimOpProp, Qualifier,
26 QualifierKind, QuantKind, RefineArg, RefineParam, RefineParams, Requires, Sort, SortDecl,
27 SortPath, SpecFunc, Spread, StaticInfo, StructDef, TraitAssocReft, TraitRef, Trusted, Ty,
28 TyAlias, TyKind, UnOp, UseTree, UseTreeKind, VariantDef, VariantRet, WhereBoundPredicate,
29 },
30 symbols::{kw, sym},
31 token::{self, Comma, Delimiter::*, IdentKind, Or, Token, TokenKind},
32};
33
34enum SyntaxAttr {
42 Reft,
44 Invariant(Expr),
46 RefinedBy(RefineParams),
48 Hide,
55 Opaque,
57 NoPanicIf(Expr),
59}
60
61#[derive(Default)]
62struct ParsedAttrs {
63 normal: Vec<Attr>,
64 syntax: Vec<SyntaxAttr>,
65}
66
67impl ParsedAttrs {
68 fn is_reft(&self) -> bool {
69 self.syntax
70 .iter()
71 .any(|attr| matches!(attr, SyntaxAttr::Reft))
72 }
73
74 fn is_hide(&self) -> bool {
75 self.syntax
76 .iter()
77 .any(|attr| matches!(attr, SyntaxAttr::Hide))
78 }
79
80 fn is_opaque(&self) -> bool {
81 self.syntax
82 .iter()
83 .any(|attr| matches!(attr, SyntaxAttr::Opaque))
84 }
85
86 fn refined_by(&mut self) -> Option<RefineParams> {
87 let pos = self
88 .syntax
89 .iter()
90 .position(|x| matches!(x, SyntaxAttr::RefinedBy(_)))?;
91 if let SyntaxAttr::RefinedBy(params) = self.syntax.remove(pos) {
92 Some(params)
93 } else {
94 None
95 }
96 }
97
98 fn no_panic_if(&mut self) -> Option<Expr> {
99 let pos = self
100 .syntax
101 .iter()
102 .position(|x| matches!(x, SyntaxAttr::NoPanicIf(_)))?;
103 if let SyntaxAttr::NoPanicIf(expr) = self.syntax.remove(pos) { Some(expr) } else { None }
104 }
105
106 fn invariant(&mut self) -> Option<Expr> {
107 let pos = self
108 .syntax
109 .iter()
110 .position(|x| matches!(x, SyntaxAttr::Invariant(_)))?;
111 if let SyntaxAttr::Invariant(exp) = self.syntax.remove(pos) { Some(exp) } else { None }
112 }
113}
114
115pub(crate) fn parse_yes_or_no_with_reason(cx: &mut ParseCtxt) -> ParseResult<bool> {
121 let mut lookahead = cx.lookahead1();
122 if lookahead.advance_if(sym::yes) {
123 if cx.advance_if(token::Comma) {
124 parse_reason(cx)?;
125 }
126 Ok(true)
127 } else if lookahead.advance_if(sym::no) {
128 if cx.advance_if(token::Comma) {
129 parse_reason(cx)?;
130 }
131 Ok(false)
132 } else if lookahead.peek(sym::reason) {
133 parse_reason(cx)?;
134 Ok(true)
135 } else {
136 Err(lookahead.into_error())
137 }
138}
139
140fn parse_reason(cx: &mut ParseCtxt) -> ParseResult {
144 cx.expect(sym::reason)?;
145 cx.expect(token::Eq)?;
146 cx.expect(AnyLit)
147}
148
149pub(crate) fn parse_ident_list(cx: &mut ParseCtxt) -> ParseResult<Vec<Ident>> {
153 punctuated_until(cx, Comma, token::Eof, parse_ident)
154}
155
156pub(crate) fn parse_flux_items(cx: &mut ParseCtxt) -> ParseResult<Vec<FluxItem>> {
160 until(cx, token::Eof, parse_flux_item)
161}
162
163fn parse_flux_item(cx: &mut ParseCtxt) -> ParseResult<FluxItem> {
172 let mut lookahead = cx.lookahead1();
173 if lookahead.peek(token::Pound) || lookahead.peek(kw::Fn) {
174 parse_reft_func(cx).map(FluxItem::FuncDef)
175 } else if lookahead.peek(kw::Local)
176 || lookahead.peek(kw::Invariant)
177 || lookahead.peek(kw::Qualifier)
178 {
179 parse_qualifier(cx).map(FluxItem::Qualifier)
180 } else if lookahead.peek(kw::Opaque) {
181 parse_sort_decl(cx).map(FluxItem::SortDecl)
182 } else if lookahead.peek(kw::Property) {
183 parse_primop_property(cx).map(FluxItem::PrimOpProp)
184 } else if lookahead.peek(kw::Axiom) {
185 parse_axiom(cx).map(FluxItem::Axiom)
186 } else if lookahead.peek(kw::Use) {
187 parse_use_item(cx).map(FluxItem::Use)
188 } else {
189 Err(lookahead.into_error())
190 }
191}
192
193pub(crate) fn parse_detached_specs(cx: &mut ParseCtxt) -> ParseResult<surface::DetachedSpecs> {
197 let items = until(cx, token::Eof, parse_detached_item)?;
198 Ok(surface::DetachedSpecs { items })
199}
200
201pub(crate) fn parse_detached_item(cx: &mut ParseCtxt) -> ParseResult<DetachedItem> {
209 let attrs = parse_attrs(cx)?;
210 let mut lookahead = cx.lookahead1();
211 if lookahead.peek(kw::Fn) {
212 Ok(parse_detached_fn_sig(cx, attrs)?.map_kind(DetachedItemKind::FnSig))
213 } else if lookahead.peek(kw::Mod) {
214 parse_detached_mod(cx)
215 } else if lookahead.peek(kw::Struct) {
216 parse_detached_struct(cx, attrs)
217 } else if lookahead.peek(kw::Enum) {
218 parse_detached_enum(cx, attrs)
219 } else if lookahead.peek(kw::Impl) {
220 parse_detached_impl(cx, attrs)
221 } else if lookahead.peek(kw::Trait) {
222 parse_detached_trait(cx, attrs)
223 } else if lookahead.peek(kw::Static) {
224 parse_detached_static(cx, attrs)
225 } else {
226 Err(lookahead.into_error())
227 }
228}
229
230fn parse_detached_field(cx: &mut ParseCtxt) -> ParseResult<(Ident, Ty)> {
234 let ident = parse_ident(cx)?;
235 cx.expect(token::Colon)?;
236 let ty = parse_type(cx)?;
237 Ok((ident, ty))
238}
239
240fn parse_detached_enum(cx: &mut ParseCtxt, mut attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
244 cx.expect(kw::Enum)?;
245 let path = parse_expr_path(cx)?;
246 let generics = Some(parse_opt_generics(cx)?);
247 let refined_by = attrs.refined_by();
248 let invariants = attrs.invariant().into_iter().collect();
249 let variants = braces(cx, Comma, |cx| parse_variant(cx, true))?
250 .into_iter()
251 .map(Some)
252 .collect();
253 let enum_def = EnumDef { generics, refined_by, variants, invariants, reflected: false };
254 Ok(DetachedItem {
255 attrs: attrs.normal,
256 path,
257 kind: DetachedItemKind::Enum(enum_def),
258 node_id: cx.next_node_id(),
259 })
260}
261
262fn parse_detached_struct(cx: &mut ParseCtxt, mut attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
263 cx.expect(kw::Struct)?;
264 let path = parse_expr_path(cx)?;
265 let generics = Some(parse_opt_generics(cx)?);
266 let refined_by = attrs.refined_by();
267 let opaque = attrs.is_opaque();
268 let invariants = attrs.invariant().into_iter().collect();
269 let fields = if cx.peek(token::OpenBrace) {
270 braces(cx, Comma, parse_detached_field)?
271 .into_iter()
272 .map(|(_, ty)| Some(ty))
273 .collect()
274 } else if cx.peek(token::OpenParen) {
275 parens(cx, Comma, parse_type)?
276 .into_iter()
277 .map(Some)
278 .collect()
279 } else {
280 cx.expect(token::Semi)?;
281 vec![]
282 };
283 let struct_def = StructDef { generics, opaque, refined_by, invariants, fields };
284 Ok(DetachedItem {
285 attrs: attrs.normal,
286 path,
287 kind: DetachedItemKind::Struct(struct_def),
288 node_id: cx.next_node_id(),
289 })
290}
291
292fn ident_path(cx: &mut ParseCtxt, ident: Ident) -> ExprPath {
293 let span = ident.span;
294 let segments = vec![ExprPathSegment { ident, node_id: cx.next_node_id() }];
295 ExprPath { segments, span, node_id: cx.next_node_id() }
296}
297
298fn parse_detached_fn_sig(
299 cx: &mut ParseCtxt,
300 mut attrs: ParsedAttrs,
301) -> ParseResult<DetachedItem<FnSig>> {
302 let mut fn_sig = parse_fn_sig(cx, token::Semi)?;
303 fn_sig.no_panic = attrs.no_panic_if();
304 let span = fn_sig.span;
305 let ident = fn_sig
306 .ident
307 .ok_or(ParseError { kind: crate::ParseErrorKind::InvalidDetachedSpec, span })?;
308 let path = ident_path(cx, ident);
309 Ok(DetachedItem { attrs: attrs.normal, path, kind: fn_sig, node_id: cx.next_node_id() })
310}
311
312fn parse_detached_static(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
316 cx.expect(kw::Static)?;
317 let path = parse_expr_path(cx)?;
318 cx.expect(token::Colon)?;
319 let ty = parse_type(cx)?;
320 cx.expect(token::Semi)?;
321 Ok(DetachedItem {
322 attrs: attrs.normal,
323 path,
324 kind: DetachedItemKind::Static(StaticInfo { ty }),
325 node_id: cx.next_node_id(),
326 })
327}
328
329fn parse_detached_mod(cx: &mut ParseCtxt) -> ParseResult<DetachedItem> {
333 cx.expect(kw::Mod)?;
334 let path = parse_expr_path(cx)?;
335 cx.expect(TokenKind::open_delim(Brace))?;
336 let items = until(cx, TokenKind::close_delim(Brace), parse_detached_item)?;
337 cx.expect(TokenKind::close_delim(Brace))?;
338 Ok(DetachedItem {
339 attrs: vec![],
340 path,
341 kind: DetachedItemKind::Mod(DetachedSpecs { items }),
342 node_id: cx.next_node_id(),
343 })
344}
345
346fn parse_detached_trait(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
350 cx.expect(kw::Trait)?;
351 let path = parse_expr_path(cx)?;
352 let _generics = parse_opt_generics(cx)?;
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)?;
359 if assoc_item_attrs.is_reft() {
360 refts.push(parse_trait_assoc_reft(cx)?);
361 } else {
362 items.push(parse_detached_fn_sig(cx, assoc_item_attrs)?);
363 }
364 }
365 cx.expect(TokenKind::close_delim(Brace))?;
366 Ok(DetachedItem {
367 attrs: attrs.normal,
368 path,
369 kind: DetachedItemKind::Trait(DetachedTrait { items, refts }),
370 node_id: cx.next_node_id(),
371 })
372}
373
374fn parse_detached_impl(cx: &mut ParseCtxt, attrs: ParsedAttrs) -> ParseResult<DetachedItem> {
378 let lo = cx.lo();
379 cx.expect(kw::Impl)?;
380 let hi = cx.hi();
381 let span = cx.mk_span(lo, hi);
382 let outer_path = parse_expr_path(cx)?;
383 let _generics = parse_opt_generics(cx)?;
384 let inner_path = if cx.advance_if(kw::For) {
385 let path = parse_expr_path(cx)?;
386 let _generics = parse_opt_generics(cx)?;
387 Some(path)
388 } else {
389 None
390 };
391 cx.expect(TokenKind::open_delim(Brace))?;
392
393 let mut items = vec![];
394 let mut refts = vec![];
395 while !cx.peek(TokenKind::close_delim(Brace)) {
396 let assoc_item_attrs = parse_attrs(cx)?;
398 if assoc_item_attrs.is_reft() && inner_path.is_some() {
399 refts.push(parse_impl_assoc_reft(cx)?);
400 } else {
401 items.push(parse_detached_fn_sig(cx, assoc_item_attrs)?);
402 }
403 }
404 cx.expect(TokenKind::close_delim(Brace))?;
405 if let Some(path) = inner_path {
406 Ok(DetachedItem {
407 attrs: attrs.normal,
408 path,
409 kind: DetachedItemKind::TraitImpl(DetachedTraitImpl {
410 trait_: outer_path,
411 items,
412 refts,
413 span,
414 }),
415 node_id: cx.next_node_id(),
416 })
417 } else {
418 Ok(DetachedItem {
419 attrs: attrs.normal,
420 path: outer_path,
421 kind: DetachedItemKind::InherentImpl(DetachedInherentImpl { items, span }),
422 node_id: cx.next_node_id(),
423 })
424 }
425}
426
427fn parse_attr(cx: &mut ParseCtxt, attrs: &mut ParsedAttrs) -> ParseResult {
428 cx.expect(token::Pound)?;
429 cx.expect(token::OpenBracket)?;
430 let mut lookahead = cx.lookahead1();
431 if lookahead.advance_if(kw::Trusted) {
432 if cx.advance_if(token::OpenParen) {
433 parse_reason(cx)?;
434 cx.expect(token::CloseParen)?;
435 }
436 attrs.normal.push(Attr::Trusted(Trusted::Yes));
437 } else if lookahead.advance_if(sym::hide) {
438 attrs.syntax.push(SyntaxAttr::Hide);
439 } else if lookahead.advance_if(kw::Opaque) {
440 attrs.syntax.push(SyntaxAttr::Opaque);
441 } else if lookahead.advance_if(kw::Reft) {
442 attrs.syntax.push(SyntaxAttr::Reft);
443 } else if lookahead.advance_if(kw::RefinedBy) {
444 attrs
445 .syntax
446 .push(SyntaxAttr::RefinedBy(delimited(cx, Parenthesis, parse_refined_by)?));
447 } else if lookahead.advance_if(kw::Invariant) {
448 attrs
449 .syntax
450 .push(SyntaxAttr::Invariant(delimited(cx, Parenthesis, |cx| parse_expr(cx, true))?));
451 } else if lookahead.advance_if(sym::no_panic_if) {
452 attrs
453 .syntax
454 .push(SyntaxAttr::NoPanicIf(parse_expr(cx, true)?));
455 } else {
456 return Err(lookahead.into_error());
457 };
458 cx.expect(token::CloseBracket)
459}
460
461fn parse_attrs(cx: &mut ParseCtxt) -> ParseResult<ParsedAttrs> {
462 let mut attrs = ParsedAttrs::default();
463 repeat_while(cx, token::Pound, |cx| parse_attr(cx, &mut attrs))?;
464 Ok(attrs)
465}
466
467fn parse_reft_func(cx: &mut ParseCtxt) -> ParseResult<SpecFunc> {
475 let attrs = parse_attrs(cx)?;
476 let hide = attrs.is_hide();
477 cx.expect(kw::Fn)?;
478 let name = parse_ident(cx)?;
479 let sort_vars = opt_angle(cx, Comma, parse_ident)?;
480 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
481 cx.expect(token::RArrow)?;
482 let output = parse_sort(cx)?;
483 let body = if cx.peek(token::OpenBrace) {
484 Some(parse_block(cx)?)
485 } else {
486 cx.expect(token::Semi)?;
487 None
488 };
489 Ok(SpecFunc { name, sort_vars, params, output, body, hide })
490}
491
492fn parse_qualifier_kind(cx: &mut ParseCtxt) -> ParseResult<QualifierKind> {
497 let mut lookahead = cx.lookahead1();
498 if lookahead.advance_if(kw::Local) {
499 Ok(QualifierKind::Local)
500 } else if lookahead.advance_if(kw::Invariant) {
501 Ok(QualifierKind::Hint)
502 } else {
503 Ok(QualifierKind::Global)
504 }
505}
506
507fn parse_qualifier(cx: &mut ParseCtxt) -> ParseResult<Qualifier> {
513 let lo = cx.lo();
514 let kind = parse_qualifier_kind(cx)?;
515 cx.expect(kw::Qualifier)?;
516 let mut name = parse_ident(cx)?;
517 let (mut params, mut wildcards): (RefineParams, Vec<bool>) =
518 parens(cx, Comma, parse_qualifier_param)?
519 .into_iter()
520 .unzip();
521 let expr = parse_block(cx)?;
522 let hi = cx.hi();
523
524 if let QualifierKind::Hint = kind {
525 let explicit: UnordSet<_> = params.iter().map(|param| param.ident).collect();
528 params.extend(
529 expr.free_vars()
530 .into_iter()
531 .filter(|ident| !explicit.contains(ident))
532 .map(|ident| {
533 RefineParam {
534 ident,
535 sort: Sort::Infer,
536 mode: None,
537 span: ident.span,
538 node_id: cx.next_node_id(),
539 }
540 }),
541 );
542 wildcards.resize(params.len(), false);
545
546 let span = name.span;
551 let str = format!(
552 "{}_{}_{}_{}",
553 name.name.to_ident_string(),
554 span.lo().0,
555 span.hi().0,
556 cx.next_node_id().as_usize()
557 );
558 name = Ident { name: Symbol::intern(&str), ..name };
559 }
560
561 debug_assert_eq!(params.len(), wildcards.len());
562 Ok(Qualifier { name, params, wildcards, expr, span: cx.mk_span(lo, hi), kind })
563}
564
565fn parse_sort_decl(cx: &mut ParseCtxt) -> ParseResult<SortDecl> {
569 cx.expect(kw::Opaque)?;
570 cx.expect(kw::Sort)?;
571 let name = parse_ident(cx)?;
572 let sort_vars = opt_angle(cx, Comma, parse_ident)?;
573 cx.expect(token::Semi)?;
574 Ok(SortDecl { name, sort_vars })
575}
576
577fn parse_binop(cx: &mut ParseCtxt) -> ParseResult<BinOp> {
579 let (op, ntokens) = cx
580 .peek_binop()
581 .ok_or_else(|| cx.unexpected_token(vec![Expected::Str("binary operator")]))?;
582 cx.advance_by(ntokens);
583 Ok(op)
584}
585
586fn parse_primop_property(cx: &mut ParseCtxt) -> ParseResult<PrimOpProp> {
590 let lo = cx.lo();
591 cx.expect(kw::Property)?;
592
593 let name = parse_ident(cx)?;
595
596 cx.expect(token::OpenBracket)?;
598 let op = parse_binop(cx)?;
599 cx.expect(token::CloseBracket)?;
600
601 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::No))?;
603
604 let body = parse_block(cx)?;
605 let hi = cx.hi();
606
607 Ok(PrimOpProp { name, op, params, body, span: cx.mk_span(lo, hi) })
608}
609
610fn parse_axiom(cx: &mut ParseCtxt) -> ParseResult<Axiom> {
614 let lo = cx.lo();
615 cx.expect(kw::Axiom)?;
616 let name = parse_ident(cx)?;
617 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
618 let body = parse_block(cx)?;
619 let hi = cx.hi();
620 Ok(Axiom { name, params, body, span: cx.mk_span(lo, hi) })
621}
622
623fn parse_use_item(cx: &mut ParseCtxt) -> ParseResult<UseTree> {
627 cx.expect(kw::Use)?;
628 let tree = parse_use_tree(cx)?;
629 cx.expect(token::Semi)?;
630 Ok(tree)
631}
632
633fn parse_use_tree(cx: &mut ParseCtxt) -> ParseResult<UseTree> {
637 let lo = cx.lo();
638 let mut segments = vec![parse_expr_path_segment(cx)?];
639 let mut hi = cx.hi();
640 let kind = loop {
641 if !cx.advance_if(token::PathSep) {
642 break UseTreeKind::Simple;
643 }
644 if cx.advance_if(token::OpenBrace) {
645 let items = punctuated_until(cx, token::Comma, token::CloseBrace, parse_use_tree)?;
646 cx.expect(token::CloseBrace)?;
647 break UseTreeKind::Nested(items);
648 }
649 segments.push(parse_expr_path_segment(cx)?);
650 hi = cx.hi();
651 };
652 let prefix = ExprPath { segments, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) };
653 Ok(UseTree { prefix, kind })
654}
655
656pub(crate) fn parse_trait_assoc_refts(cx: &mut ParseCtxt) -> ParseResult<Vec<TraitAssocReft>> {
657 until(cx, token::Eof, parse_trait_assoc_reft)
658}
659
660fn parse_trait_assoc_reft(cx: &mut ParseCtxt) -> ParseResult<TraitAssocReft> {
666 let lo = cx.lo();
667 let final_ = cx.advance_if(kw::Final);
668 cx.expect(kw::Fn)?;
669 let name = parse_ident(cx)?;
670 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
671 cx.expect(token::RArrow)?;
672 let output = parse_base_sort(cx)?;
673 let body = if cx.peek(token::OpenBrace) {
674 Some(parse_block(cx)?)
675 } else {
676 cx.advance_if(token::Semi);
677 None
678 };
679 let hi = cx.hi();
680 Ok(TraitAssocReft { name, params, output, body, span: cx.mk_span(lo, hi), final_ })
681}
682
683pub(crate) fn parse_impl_assoc_refts(cx: &mut ParseCtxt) -> ParseResult<Vec<ImplAssocReft>> {
684 until(cx, token::Eof, parse_impl_assoc_reft)
685}
686
687fn parse_impl_assoc_reft(cx: &mut ParseCtxt) -> ParseResult<ImplAssocReft> {
691 let lo = cx.lo();
692 cx.expect(kw::Fn)?;
693 let name = parse_ident(cx)?;
694 let params = parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?;
695 cx.expect(token::RArrow)?;
696 let output = parse_base_sort(cx)?;
697 let body = parse_block(cx)?;
698 let hi = cx.hi();
699 Ok(ImplAssocReft { name, params, output, body, span: cx.mk_span(lo, hi) })
700}
701
702pub(crate) fn parse_refined_by(cx: &mut ParseCtxt) -> ParseResult<RefineParams> {
706 punctuated_until(cx, Comma, token::Eof, |cx| parse_refine_param(cx, RequireSort::Yes))
707}
708
709pub(crate) fn parse_variant(cx: &mut ParseCtxt, ret_arrow: bool) -> ParseResult<VariantDef> {
715 let lo = cx.lo();
716 let mut fields = vec![];
717 let mut ret = None;
718 let ident = if ret_arrow || cx.peek2(NonReserved, token::OpenParen) {
719 Some(parse_ident(cx)?)
720 } else {
721 None
722 };
723 if cx.peek(token::OpenParen) || cx.peek(token::OpenBrace) {
724 fields = parse_fields(cx)?;
725 if cx.advance_if(token::RArrow) {
726 ret = Some(parse_variant_ret(cx)?);
727 }
728 } else {
729 if ret_arrow {
730 cx.expect(token::RArrow)?;
731 }
732 ret = Some(parse_variant_ret(cx)?);
733 };
734 let hi = cx.hi();
735 Ok(VariantDef { ident, fields, ret, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
736}
737
738fn parse_fields(cx: &mut ParseCtxt) -> ParseResult<Vec<Ty>> {
742 let mut lookahead = cx.lookahead1();
743 if lookahead.peek(token::OpenParen) {
744 parens(cx, Comma, parse_type)
745 } else if lookahead.peek(token::OpenBrace) {
746 braces(cx, Comma, parse_type)
747 } else {
748 Err(lookahead.into_error())
749 }
750}
751
752fn parse_variant_ret(cx: &mut ParseCtxt) -> ParseResult<VariantRet> {
756 let path = parse_path(cx)?;
757 let indices = if cx.peek(token::OpenBracket) {
758 parse_indices(cx)?
759 } else {
760 let hi = cx.hi();
761 Indices { indices: vec![], span: cx.mk_span(hi, hi) }
762 };
763 Ok(VariantRet { path, indices })
764}
765
766pub(crate) fn parse_type_alias(cx: &mut ParseCtxt) -> ParseResult<TyAlias> {
767 let lo = cx.lo();
768 cx.expect(kw::Type)?;
769 let ident = parse_ident(cx)?;
770 let generics = parse_opt_generics(cx)?;
771 let params = if cx.peek(token::OpenParen) {
772 parens(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Yes))?
773 } else {
774 vec![]
775 };
776 let index = if cx.peek(token::OpenBracket) {
777 Some(delimited(cx, Bracket, |cx| parse_refine_param(cx, RequireSort::Yes))?)
778 } else {
779 None
780 };
781 cx.expect(token::Eq)?;
782 let ty = parse_type(cx)?;
783 let hi = cx.hi();
784 Ok(TyAlias {
785 ident,
786 generics,
787 params,
788 index,
789 ty,
790 node_id: cx.next_node_id(),
791 span: cx.mk_span(lo, hi),
792 })
793}
794
795fn parse_opt_generics(cx: &mut ParseCtxt) -> ParseResult<Generics> {
796 if !cx.peek(LAngle) {
797 let hi = cx.hi();
798 return Ok(Generics { params: vec![], predicates: None, span: cx.mk_span(hi, hi) });
799 }
800 let lo = cx.lo();
801 let params = angle(cx, Comma, parse_generic_param)?;
802 let hi = cx.hi();
803 Ok(Generics { params, predicates: None, span: cx.mk_span(lo, hi) })
804}
805
806fn parse_generic_param(cx: &mut ParseCtxt) -> ParseResult<GenericParam> {
807 let name = parse_ident(cx)?;
808 Ok(GenericParam { name, node_id: cx.next_node_id() })
809}
810
811fn invalid_ident_err(ident: &Ident) -> ParseError {
812 ParseError { kind: crate::ParseErrorKind::InvalidBinding, span: ident.span }
813}
814
815fn mut_as_strg(inputs: Vec<FnInput>, ensures: &[Ensures]) -> ParseResult<Vec<FnInput>> {
816 let locs = ensures
818 .iter()
819 .filter_map(|ens| if let Ensures::Type(ident, _, _) = ens { Some(ident) } else { None })
820 .collect::<HashSet<_>>();
821 let mut res = vec![];
823 for input in inputs {
824 if let FnInput::Ty(Some(ident), _, _) = &input
825 && locs.contains(&ident)
826 {
827 let FnInput::Ty(Some(ident), ty, id) = input else {
829 return Err(invalid_ident_err(ident));
830 };
831 let TyKind::Ref(Mutability::Mut, inner_ty) = ty.kind else {
832 return Err(invalid_ident_err(&ident));
833 };
834 res.push(FnInput::StrgRef(ident, *inner_ty, id));
835 } else {
836 res.push(input);
838 }
839 }
840 Ok(res)
841}
842
843pub(crate) fn parse_fn_sig<T: PeekExpected>(cx: &mut ParseCtxt, end: T) -> ParseResult<FnSig> {
851 let lo = cx.lo();
852 let asyncness = parse_asyncness(cx);
853 cx.expect(kw::Fn)?;
854 let ident = if cx.peek(NonReserved) { Some(parse_ident(cx)?) } else { None };
855 let mut generics = parse_opt_generics(cx)?;
856 let params = if cx.peek(token::OpenBracket) {
857 brackets(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?
858 } else {
859 vec![]
860 };
861 let inputs = parens(cx, Comma, parse_fn_input)?;
862 let returns = parse_fn_ret(cx)?;
863 let requires = parse_opt_requires(cx)?;
864 let ensures = parse_opt_ensures(cx)?;
865 let inputs = mut_as_strg(inputs, &ensures)?;
866 generics.predicates = parse_opt_where(cx)?;
867 cx.expect(end)?;
868 let hi = cx.hi();
869 Ok(FnSig {
870 asyncness,
871 generics,
872 params,
873 ident,
874 inputs,
875 requires,
876 output: FnOutput { returns, ensures, node_id: cx.next_node_id() },
877 node_id: cx.next_node_id(),
878 span: cx.mk_span(lo, hi),
879 no_panic: None, })
881}
882
883fn parse_opt_requires(cx: &mut ParseCtxt) -> ParseResult<Vec<Requires>> {
887 if !cx.advance_if(kw::Requires) {
888 return Ok(vec![]);
889 }
890 punctuated_until(
891 cx,
892 Comma,
893 |t: TokenKind| t.is_keyword(kw::Ensures) || t.is_keyword(kw::Where) || t.is_eof(),
894 parse_requires_clause,
895 )
896}
897
898fn parse_requires_clause(cx: &mut ParseCtxt) -> ParseResult<Requires> {
902 let mut params = vec![];
903 if cx.advance_if(kw::Forall) {
904 params = sep1(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
905 cx.expect(token::Dot)?;
906 }
907 let pred = parse_expr(cx, true)?;
908 Ok(Requires { params, pred })
909}
910
911fn parse_opt_ensures(cx: &mut ParseCtxt) -> ParseResult<Vec<Ensures>> {
915 if !cx.advance_if(kw::Ensures) {
916 return Ok(vec![]);
917 }
918 punctuated_until(
919 cx,
920 Comma,
921 |t: TokenKind| t.is_keyword(kw::Where) || t.is_eof(),
922 parse_ensures_clause,
923 )
924}
925
926fn parse_ensures_clause(cx: &mut ParseCtxt) -> ParseResult<Ensures> {
931 if cx.peek2(NonReserved, token::Colon) {
932 let ident = parse_ident(cx)?;
934 cx.expect(token::Colon)?;
935 let ty = parse_type(cx)?;
936 Ok(Ensures::Type(ident, ty, cx.next_node_id()))
937 } else {
938 Ok(Ensures::Pred(parse_expr(cx, true)?))
940 }
941}
942
943fn parse_opt_where(cx: &mut ParseCtxt) -> ParseResult<Option<Vec<WhereBoundPredicate>>> {
944 if !cx.advance_if(kw::Where) {
945 return Ok(None);
946 }
947 Ok(Some(punctuated_until(cx, Comma, token::Eof, parse_where_bound)?))
948}
949
950fn parse_where_bound(cx: &mut ParseCtxt) -> ParseResult<WhereBoundPredicate> {
951 let lo = cx.lo();
952 let bounded_ty = parse_type(cx)?;
953 cx.expect(token::Colon)?;
954 let bounds = parse_generic_bounds(cx)?;
955 let hi = cx.hi();
956 Ok(WhereBoundPredicate { span: cx.mk_span(lo, hi), bounded_ty, bounds })
957}
958
959fn parse_fn_ret(cx: &mut ParseCtxt) -> ParseResult<FnRetTy> {
963 if cx.advance_if(token::RArrow) {
964 Ok(FnRetTy::Ty(Box::new(parse_type(cx)?)))
965 } else {
966 let hi = cx.hi();
967 Ok(FnRetTy::Default(cx.mk_span(hi, hi)))
968 }
969}
970
971fn parse_fn_input(cx: &mut ParseCtxt) -> ParseResult<FnInput> {
978 if cx.peek2(NonReserved, token::Colon) {
979 let bind = parse_ident(cx)?;
980 cx.expect(token::Colon)?;
981 if cx.advance_if2(token::And, kw::Strg) {
982 Ok(FnInput::StrgRef(bind, parse_type(cx)?, cx.next_node_id()))
984 } else if cx.peek(NonReserved) {
985 let path = parse_path(cx)?;
986 if cx.peek3(token::OpenBrace, NonReserved, token::Colon) {
987 let bty = path_to_bty(path);
989 let ty = parse_bty_exists(cx, bty)?;
990 Ok(FnInput::Ty(Some(bind), ty, cx.next_node_id()))
991 } else if cx.peek(token::OpenBrace) {
992 let pred = delimited(cx, Brace, |cx| parse_expr(cx, true))?;
994 Ok(FnInput::Constr(bind, path, pred, cx.next_node_id()))
995 } else {
996 let bty = path_to_bty(path);
998 let ty = parse_bty_rhs(cx, bty)?;
999 Ok(FnInput::Ty(Some(bind), ty, cx.next_node_id()))
1000 }
1001 } else {
1002 Ok(FnInput::Ty(Some(bind), parse_type(cx)?, cx.next_node_id()))
1004 }
1005 } else {
1006 Ok(FnInput::Ty(None, parse_type(cx)?, cx.next_node_id()))
1008 }
1009}
1010
1011fn parse_asyncness(cx: &mut ParseCtxt) -> Async {
1015 let lo = cx.lo();
1016 if cx.advance_if(kw::Async) {
1017 Async::Yes { node_id: cx.next_node_id(), span: cx.mk_span(lo, cx.hi()) }
1018 } else {
1019 Async::No
1020 }
1021}
1022
1023enum Reft {
1024 Exi(Ident, Expr),
1025 Idx(Indices),
1026 None,
1027}
1028
1029fn parse_reft(cx: &mut ParseCtxt) -> ParseResult<Reft> {
1030 if cx.peek(token::OpenBrace) {
1031 let (bind, pred) = delimited(cx, Brace, |cx| {
1032 let bind = parse_ident(cx)?;
1033 cx.expect(token::Colon)?;
1034 let pred = parse_block_expr(cx)?;
1035 Ok((bind, pred))
1036 })?;
1037 Ok(Reft::Exi(bind, pred))
1038 } else if cx.peek(token::OpenBracket) {
1039 let indices = parse_indices(cx)?;
1040 Ok(Reft::Idx(indices))
1041 } else {
1042 Ok(Reft::None)
1043 }
1044}
1045
1046pub(crate) fn parse_type(cx: &mut ParseCtxt) -> ParseResult<Ty> {
1065 let lo = cx.lo();
1066 let mut lookahead = cx.lookahead1();
1067 let kind = if lookahead.advance_if(kw::Underscore) {
1068 TyKind::Hole
1069 } else if lookahead.advance_if(token::OpenParen) {
1070 let (mut tys, trailing) =
1072 punctuated_with_trailing(cx, Comma, token::CloseParen, parse_type)?;
1073 cx.expect(token::CloseParen)?;
1074 if tys.len() == 1 && !trailing {
1075 return Ok(tys.remove(0));
1076 } else {
1077 TyKind::Tuple(tys)
1078 }
1079 } else if lookahead.peek(token::OpenBrace) {
1080 delimited(cx, Brace, |cx| {
1081 if cx.peek2(NonReserved, AnyOf([token::Comma, token::Dot, token::Colon])) {
1082 parse_general_exists(cx)
1084 } else {
1085 let ty = parse_type(cx)?;
1087 cx.expect(token::Or)?;
1088 let pred = parse_block_expr(cx)?;
1089 Ok(TyKind::Constr(pred, Box::new(ty)))
1090 }
1091 })?
1092 } else if lookahead.advance_if(token::And) {
1093 let mutbl = if cx.advance_if(kw::Mut) { Mutability::Mut } else { Mutability::Not };
1095 TyKind::Ref(mutbl, Box::new(parse_type(cx)?))
1096 } else if lookahead.advance_if(token::Star) {
1097 let mutbl = if cx.advance_if(kw::Mut) {
1099 Mutability::Mut
1100 } else {
1101 cx.expect(kw::Const)?;
1102 Mutability::Not
1103 };
1104 let reft = parse_reft(cx)?;
1106 let inner_ty = parse_type(cx)?;
1107 let bty = BaseTy {
1108 kind: BaseTyKind::Ptr(mutbl, Box::new(inner_ty)),
1109 span: cx.mk_span(lo, cx.hi()),
1110 };
1111 match reft {
1112 Reft::Exi(bind, pred) => TyKind::Exists { bind, bty, pred },
1113 Reft::Idx(indices) => TyKind::Indexed { bty, indices },
1114 Reft::None => TyKind::Base(bty),
1115 }
1116 } else if lookahead.advance_if(token::OpenBracket) {
1117 let ty = parse_type(cx)?;
1118 if cx.advance_if(token::Semi) {
1119 let len = parse_const_arg(cx)?;
1121 cx.expect(token::CloseBracket)?;
1122 TyKind::Array(Box::new(ty), len)
1123 } else {
1124 cx.expect(token::CloseBracket)?;
1126 let span = cx.mk_span(lo, cx.hi());
1127 let kind = BaseTyKind::Slice(Box::new(ty));
1128 return parse_bty_rhs(cx, BaseTy { kind, span });
1129 }
1130 } else if lookahead.advance_if(kw::Impl) {
1131 TyKind::ImplTrait(cx.next_node_id(), parse_generic_bounds(cx)?)
1133 } else if lookahead.peek(kw::Fn) || lookahead.peek(kw::Unsafe) || lookahead.peek(kw::Extern) {
1134 let safety =
1136 if cx.advance_if(kw::Unsafe) { surface::Safety::Unsafe } else { surface::Safety::Safe };
1137 let abi = if cx.peek(kw::Extern) {
1138 let extern_lo = cx.lo();
1139 cx.advance();
1140 if let Token { kind: token::Literal(Lit { kind: LitKind::Str, symbol, .. }), lo, hi } =
1141 cx.at(0)
1142 {
1143 cx.advance();
1144 Some(Ident { name: symbol, span: cx.mk_span(lo, hi) })
1145 } else {
1146 Some(Ident { name: sym::C, span: cx.mk_span(extern_lo, cx.hi()) })
1148 }
1149 } else {
1150 None
1151 };
1152 cx.expect(kw::Fn)?;
1153 let inputs = parens(cx, Comma, parse_type)?;
1154 let output = parse_fn_ret(cx)?;
1155 let span = cx.mk_span(lo, cx.hi());
1156 TyKind::BareFn(Box::new(BareFnTy {
1157 safety,
1158 abi,
1159 inputs,
1160 output,
1161 node_id: cx.next_node_id(),
1162 span,
1163 }))
1164 } else if lookahead.peek(NonReserved) {
1165 let path = parse_path(cx)?;
1167 let bty = path_to_bty(path);
1168 return parse_bty_rhs(cx, bty);
1169 } else if lookahead.peek(LAngle) {
1170 let bty = parse_qpath(cx)?;
1172 return parse_bty_rhs(cx, bty);
1173 } else {
1174 return Err(lookahead.into_error());
1175 };
1176 let hi = cx.hi();
1177 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1178}
1179
1180fn parse_qpath(cx: &mut ParseCtxt) -> ParseResult<BaseTy> {
1184 let lo = cx.lo();
1185 cx.expect(LAngle)?;
1186 let qself = parse_type(cx)?;
1187 cx.expect(kw::As)?;
1188 let mut segments = parse_segments(cx)?;
1189 cx.expect(RAngle)?;
1190 cx.expect(token::PathSep)?;
1191 segments.extend(parse_segments(cx)?);
1192 let hi = cx.hi();
1193
1194 let span = cx.mk_span(lo, hi);
1195 let path = Path { segments, refine: vec![], node_id: cx.next_node_id(), span };
1196 let kind = BaseTyKind::Path(Some(Box::new(qself)), path);
1197 Ok(BaseTy { kind, span })
1198}
1199
1200fn parse_general_exists(cx: &mut ParseCtxt) -> ParseResult<TyKind> {
1204 let params = sep1(cx, Comma, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
1205 cx.expect(token::Dot)?;
1206 let ty = parse_type(cx)?;
1207 let pred = if cx.advance_if(token::Or) { Some(parse_block_expr(cx)?) } else { None };
1208 Ok(TyKind::GeneralExists { params, ty: Box::new(ty), pred })
1209}
1210
1211fn parse_bty_rhs(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
1217 let lo = bty.span.lo();
1218 if cx.peek(token::OpenBracket) {
1219 let indices = parse_indices(cx)?;
1221 let hi = cx.hi();
1222 let kind = TyKind::Indexed { bty, indices };
1223 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1224 } else if cx.peek(token::OpenBrace) {
1225 parse_bty_exists(cx, bty)
1227 } else {
1228 let hi = cx.hi();
1230 let kind = TyKind::Base(bty);
1231 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1232 }
1233}
1234
1235fn parse_bty_exists(cx: &mut ParseCtxt, bty: BaseTy) -> ParseResult<Ty> {
1239 let lo = bty.span.lo();
1240 delimited(cx, Brace, |cx| {
1241 let bind = parse_ident(cx)?;
1242 cx.expect(token::Colon)?;
1243 let pred = parse_block_expr(cx)?;
1244 let hi = cx.hi();
1245 let kind = TyKind::Exists { bind, bty, pred };
1246 Ok(Ty { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1247 })
1248}
1249
1250fn path_to_bty(path: Path) -> BaseTy {
1251 let span = path.span;
1252 BaseTy { kind: BaseTyKind::Path(None, path), span }
1253}
1254
1255fn parse_indices(cx: &mut ParseCtxt) -> ParseResult<Indices> {
1256 let lo = cx.lo();
1257 let indices = brackets(cx, Comma, parse_refine_arg)?;
1258 let hi = cx.hi();
1259 Ok(Indices { indices, span: cx.mk_span(lo, hi) })
1260}
1261
1262fn parse_fn_bound_input(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1263 let lo = cx.lo();
1264 let tys = parens(cx, Comma, parse_type)?;
1265 let hi = cx.hi();
1266 let kind = TyKind::Tuple(tys);
1267 let span = cx.mk_span(lo, hi);
1268 let in_ty = Ty { kind, node_id: cx.next_node_id(), span };
1269 Ok(GenericArg { kind: GenericArgKind::Type(in_ty), node_id: cx.next_node_id() })
1270}
1271
1272fn parse_fn_bound_output(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1273 let lo = cx.lo();
1274
1275 let ty = if cx.advance_if(token::RArrow) {
1276 parse_type(cx)?
1277 } else {
1278 Ty { kind: TyKind::Tuple(vec![]), node_id: cx.next_node_id(), span: cx.mk_span(lo, lo) }
1279 };
1280 let hi = cx.hi();
1281 let ident = Ident { name: Output, span: cx.mk_span(lo, hi) };
1282 Ok(GenericArg { kind: GenericArgKind::Constraint(ident, ty), node_id: cx.next_node_id() })
1283}
1284
1285fn parse_fn_bound_path(cx: &mut ParseCtxt) -> ParseResult<Path> {
1286 let lo = cx.lo();
1287 let ident = parse_ident(cx)?;
1288 let in_arg = parse_fn_bound_input(cx)?;
1289 let out_arg = parse_fn_bound_output(cx)?;
1290 let args = vec![in_arg, out_arg];
1291 let segment = PathSegment { ident, args, node_id: cx.next_node_id() };
1292 let hi = cx.hi();
1293 Ok(Path {
1294 segments: vec![segment],
1295 refine: vec![],
1296 node_id: cx.next_node_id(),
1297 span: cx.mk_span(lo, hi),
1298 })
1299}
1300
1301fn parse_generic_bounds(cx: &mut ParseCtxt) -> ParseResult<GenericBounds> {
1302 let path = if cx.peek(sym::FnOnce) || cx.peek(sym::FnMut) || cx.peek(sym::Fn) {
1303 parse_fn_bound_path(cx)?
1304 } else {
1305 parse_path(cx)?
1306 };
1307 Ok(vec![TraitRef { path, node_id: cx.next_node_id() }])
1308}
1309
1310fn parse_const_arg(cx: &mut ParseCtxt) -> ParseResult<ConstArg> {
1311 let lo = cx.lo();
1312 let mut lookahead = cx.lookahead1();
1313 let kind = if lookahead.peek(AnyLit) {
1314 let len = parse_int(cx)?;
1315 ConstArgKind::Lit(len)
1316 } else if lookahead.peek(NonReserved) {
1317 ConstArgKind::Path(parse_path(cx)?)
1318 } else if lookahead.advance_if(kw::Underscore) {
1319 ConstArgKind::Infer
1320 } else {
1321 return Err(lookahead.into_error());
1322 };
1323 let hi = cx.hi();
1324 Ok(ConstArg { kind, span: cx.mk_span(lo, hi) })
1325}
1326
1327fn parse_path(cx: &mut ParseCtxt) -> ParseResult<Path> {
1331 let lo = cx.lo();
1332 let segments = parse_segments(cx)?;
1333 let refine =
1334 if cx.peek(token::OpenParen) { parens(cx, Comma, parse_refine_arg)? } else { vec![] };
1335 let hi = cx.hi();
1336 Ok(Path { segments, refine, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1337}
1338
1339fn parse_segments(cx: &mut ParseCtxt) -> ParseResult<Vec<PathSegment>> {
1343 sep1(cx, token::PathSep, parse_segment)
1344}
1345
1346fn parse_segment(cx: &mut ParseCtxt) -> ParseResult<PathSegment> {
1350 let ident = parse_ident(cx)?;
1351 let args = opt_angle(cx, Comma, parse_generic_arg)?;
1352 Ok(PathSegment { ident, node_id: cx.next_node_id(), args })
1353}
1354
1355fn parse_generic_arg(cx: &mut ParseCtxt) -> ParseResult<GenericArg> {
1359 let kind = if cx.peek2(NonReserved, token::Eq) {
1360 let ident = parse_ident(cx)?;
1361 cx.expect(token::Eq)?;
1362 let ty = parse_type(cx)?;
1363 GenericArgKind::Constraint(ident, ty)
1364 } else {
1365 GenericArgKind::Type(parse_type(cx)?)
1366 };
1367 Ok(GenericArg { kind, node_id: cx.next_node_id() })
1368}
1369
1370fn parse_refine_arg(cx: &mut ParseCtxt) -> ParseResult<RefineArg> {
1377 let lo = cx.lo();
1378 let arg = if cx.advance_if(token::At) {
1379 let bind = parse_ident(cx)?;
1381 let hi = cx.hi();
1382 RefineArg::Bind(bind, BindKind::At, cx.mk_span(lo, hi), cx.next_node_id())
1383 } else if cx.peek2(token::Pound, NonReserved) {
1384 cx.expect(token::Pound)?;
1386 let bind = parse_ident(cx)?;
1387 let hi = cx.hi();
1388 RefineArg::Bind(bind, BindKind::Pound, cx.mk_span(lo, hi), cx.next_node_id())
1389 } else if cx.advance_if(Or) {
1390 let params =
1391 punctuated_until(cx, Comma, Or, |cx| parse_refine_param(cx, RequireSort::Maybe))?;
1392 cx.expect(Or)?;
1393 let body = parse_expr(cx, true)?;
1394 let hi = cx.hi();
1395 RefineArg::Abs(params, body, cx.mk_span(lo, hi), cx.next_node_id())
1396 } else {
1397 RefineArg::Expr(parse_expr(cx, true)?)
1399 };
1400 Ok(arg)
1401}
1402
1403enum RequireSort {
1405 Yes,
1407 Maybe,
1409 No,
1411}
1412
1413fn parse_sort_if_required(cx: &mut ParseCtxt, require_sort: RequireSort) -> ParseResult<Sort> {
1414 match require_sort {
1415 RequireSort::No => Ok(Sort::Infer),
1416 RequireSort::Maybe => {
1417 if cx.advance_if(token::Colon) {
1418 parse_sort(cx)
1419 } else {
1420 Ok(Sort::Infer)
1421 }
1422 }
1423 RequireSort::Yes => {
1424 cx.expect(token::Colon)?;
1425 parse_sort(cx)
1426 }
1427 }
1428}
1429
1430fn parse_refine_param(cx: &mut ParseCtxt, require_sort: RequireSort) -> ParseResult<RefineParam> {
1436 let lo = cx.lo();
1437 let mode = parse_opt_param_mode(cx);
1438 let ident = parse_ident(cx)?;
1439 let sort = parse_sort_if_required(cx, require_sort)?;
1440 let hi = cx.hi();
1441 Ok(RefineParam { mode, ident, sort, span: cx.mk_span(lo, hi), node_id: cx.next_node_id() })
1442}
1443
1444fn parse_qualifier_param(cx: &mut ParseCtxt) -> ParseResult<(RefineParam, bool)> {
1451 let is_wildcard = cx.advance_if(token::Pound);
1452 let param = parse_refine_param(cx, RequireSort::Yes)?;
1453 Ok((param, is_wildcard))
1454}
1455
1456fn parse_opt_param_mode(cx: &mut ParseCtxt) -> Option<ParamMode> {
1460 if cx.advance_if(kw::Hrn) {
1461 Some(ParamMode::Horn)
1462 } else if cx.advance_if(kw::Hdl) {
1463 Some(ParamMode::Hindley)
1464 } else {
1465 None
1466 }
1467}
1468
1469pub(crate) fn parse_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1470 parse_binops(cx, Precedence::MIN, allow_struct)
1471}
1472
1473fn parse_binops(cx: &mut ParseCtxt, base: Precedence, allow_struct: bool) -> ParseResult<Expr> {
1474 let mut lhs = unary_expr(cx, allow_struct)?;
1475 loop {
1476 let lo = cx.lo();
1477 let Some((op, ntokens)) = cx.peek_binop() else { break };
1478 let precedence = Precedence::of_binop(&op);
1479 if precedence < base {
1480 break;
1481 }
1482 cx.advance_by(ntokens);
1483 let next = match precedence.associativity() {
1484 Associativity::Right => precedence,
1485 Associativity::Left => precedence.next(),
1486 Associativity::None => {
1487 if let ExprKind::BinaryOp(op, ..) = &lhs.kind
1488 && Precedence::of_binop(op) == precedence
1489 {
1490 return Err(cx.cannot_be_chained(lo, cx.hi()));
1491 }
1492 precedence.next()
1493 }
1494 };
1495 let rhs = parse_binops(cx, next, allow_struct)?;
1496 let span = lhs.span.to(rhs.span);
1497 lhs = Expr {
1498 kind: ExprKind::BinaryOp(op, Box::new([lhs, rhs])),
1499 node_id: cx.next_node_id(),
1500 span,
1501 }
1502 }
1503 Ok(lhs)
1504}
1505
1506fn unary_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1510 let lo = cx.lo();
1511 let kind = if cx.advance_if(token::Minus) {
1512 ExprKind::UnaryOp(UnOp::Neg, Box::new(unary_expr(cx, allow_struct)?))
1513 } else if cx.advance_if(token::Bang) {
1514 ExprKind::UnaryOp(UnOp::Not, Box::new(unary_expr(cx, allow_struct)?))
1515 } else {
1516 return parse_trailer_expr(cx, allow_struct);
1517 };
1518 let hi = cx.hi();
1519 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1520}
1521
1522fn parse_trailer_expr(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1529 let lo = cx.lo();
1530 let mut e = parse_atom(cx, allow_struct)?;
1531 loop {
1532 let kind = if cx.advance_if(token::Dot) {
1533 if let Token { kind: token::Literal(lit), lo, hi } = cx.at(0)
1534 && let Lit { kind: LitKind::Integer, symbol: name, suffix: None, .. } = lit
1535 {
1536 cx.advance();
1538 ExprKind::Dot(Box::new(e), Ident { name, span: cx.mk_span(lo, hi) })
1539 } else {
1540 let field = parse_ident(cx)?;
1542 ExprKind::Dot(Box::new(e), field)
1543 }
1544 } else if cx.peek(token::OpenParen) {
1545 let args = parens(cx, Comma, |cx| parse_expr(cx, true))?;
1547 ExprKind::Call(Box::new(e), args)
1548 } else {
1549 break;
1550 };
1551 let hi = cx.hi();
1552 e = Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) };
1553 }
1554 Ok(e)
1555}
1556
1557fn parse_atom(cx: &mut ParseCtxt, allow_struct: bool) -> ParseResult<Expr> {
1571 let lo = cx.lo();
1572 let mut lookahead = cx.lookahead1();
1573 if lookahead.peek(kw::If) {
1574 parse_if_expr(cx)
1576 } else if lookahead.peek(AnyLit) {
1577 parse_lit(cx)
1579 } else if lookahead.advance_if(token::OpenParen) {
1580 let (mut exprs, trailing) =
1582 punctuated_with_trailing(cx, Comma, token::CloseParen, |cx| parse_expr(cx, true))?;
1583 cx.expect(token::CloseParen)?;
1584 if exprs.len() == 1 && !trailing {
1585 Ok(exprs.remove(0))
1586 } else {
1587 Ok(Expr {
1588 kind: ExprKind::Tuple(exprs),
1589 node_id: cx.next_node_id(),
1590 span: cx.mk_span(lo, cx.hi()),
1591 })
1592 }
1593 } else if lookahead.advance_if(token::Pound) {
1594 let lo = cx.lo();
1596 let exprs = braces(cx, Comma, |cx| parse_expr(cx, true))?;
1597 let hi = cx.hi();
1598 let kind = ExprKind::SetLiteral(exprs);
1599 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1600 } else if lookahead.peek(NonReserved) {
1601 let path = parse_expr_path(cx)?;
1602 let kind = if allow_struct && cx.peek(token::OpenBrace) {
1603 let args = braces(cx, Comma, parse_constructor_arg)?;
1605 ExprKind::Constructor(Some(path), args)
1606 } else {
1607 ExprKind::Path(path)
1609 };
1610 let hi = cx.hi();
1611 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1612 } else if allow_struct && lookahead.peek(token::OpenBrace) {
1613 let args = braces(cx, Comma, parse_constructor_arg)?;
1615 let hi = cx.hi();
1616 Ok(Expr {
1617 kind: ExprKind::Constructor(None, args),
1618 node_id: cx.next_node_id(),
1619 span: cx.mk_span(lo, hi),
1620 })
1621 } else if lookahead.advance_if(LAngle) {
1622 let lo = cx.lo();
1624 let qself = parse_type(cx)?;
1625 cx.expect(kw::As)?;
1626 let path = parse_path(cx)?;
1627 cx.expect(RAngle)?;
1628 cx.expect(token::PathSep)?;
1629 let name = parse_ident(cx)?;
1630 let hi = cx.hi();
1631 let kind = ExprKind::AssocReft(Box::new(qself), path, name);
1632 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1633 } else if lookahead.peek(token::OpenBracket) {
1634 parse_prim_uif(cx)
1635 } else if lookahead.peek(kw::Exists) || lookahead.peek(kw::Forall) {
1636 parse_quantifier(cx)
1637 } else {
1638 Err(lookahead.into_error())
1639 }
1640}
1641
1642fn parse_prim_uif(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1643 let lo = cx.lo();
1644 cx.expect(token::OpenBracket)?;
1645 let op = parse_binop(cx)?;
1646 cx.expect(token::CloseBracket)?;
1647 let hi = cx.hi();
1648 Ok(Expr { kind: ExprKind::PrimUIF(op), node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1649}
1650
1651fn parse_quantifier(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1658 let lo = cx.lo();
1659 let mut lookahead = cx.lookahead1();
1660 let quant = if lookahead.advance_if(kw::Forall) {
1661 QuantKind::Forall
1662 } else if lookahead.advance_if(kw::Exists) {
1663 QuantKind::Exists
1664 } else {
1665 return Err(lookahead.into_error());
1666 };
1667 let param = parse_refine_param(cx, RequireSort::Maybe)?;
1668
1669 let mut lookahead = cx.lookahead1();
1670 let dom = if lookahead.peek(kw::In) {
1671 cx.expect(kw::In)?;
1672 let start = parse_int(cx)?;
1673 cx.expect(token::DotDot)?;
1674 let end = parse_int(cx)?;
1675 Some(start..end)
1676 } else {
1677 None
1678 };
1679 let body = parse_block(cx)?;
1680 let hi = cx.hi();
1681 let kind = ExprKind::Quant(quant, param, dom, Box::new(body));
1682 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1683}
1684
1685fn parse_constructor_arg(cx: &mut ParseCtxt) -> ParseResult<ConstructorArg> {
1689 let lo = cx.lo();
1690 let mut lookahead = cx.lookahead1();
1691 if lookahead.peek(NonReserved) {
1692 let ident = parse_ident(cx)?;
1693 cx.expect(token::Colon)?;
1694 let expr = parse_refine_arg(cx)?;
1695 let hi = cx.hi();
1696 Ok(ConstructorArg::FieldExpr(FieldExpr {
1697 ident,
1698 expr,
1699 node_id: cx.next_node_id(),
1700 span: cx.mk_span(lo, hi),
1701 }))
1702 } else if lookahead.advance_if(token::DotDot) {
1703 let spread = parse_expr(cx, true)?;
1704 let hi = cx.hi();
1705 Ok(ConstructorArg::Spread(Spread {
1706 expr: spread,
1707 node_id: cx.next_node_id(),
1708 span: cx.mk_span(lo, hi),
1709 }))
1710 } else {
1711 Err(lookahead.into_error())
1712 }
1713}
1714
1715fn parse_expr_path(cx: &mut ParseCtxt) -> ParseResult<ExprPath> {
1717 let lo = cx.lo();
1718 let segments = sep1(cx, token::PathSep, parse_expr_path_segment)?;
1719 let hi = cx.hi();
1720 Ok(ExprPath { segments, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1721}
1722
1723fn parse_expr_path_segment(cx: &mut ParseCtxt) -> ParseResult<ExprPathSegment> {
1724 Ok(ExprPathSegment { ident: parse_ident(cx)?, node_id: cx.next_node_id() })
1725}
1726
1727fn parse_if_expr(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1731 let mut branches = vec![];
1732
1733 loop {
1734 let lo = cx.lo();
1735 cx.expect(kw::If)?;
1736 let cond = parse_expr(cx, false)?;
1737 let then_ = parse_block(cx)?;
1738 branches.push((lo, cond, then_));
1739 cx.expect(kw::Else)?;
1740
1741 if !cx.peek(kw::If) {
1742 break;
1743 }
1744 }
1745 let mut else_ = parse_block(cx)?;
1746
1747 let hi = cx.hi();
1748 while let Some((lo, cond, then_)) = branches.pop() {
1749 else_ = Expr {
1750 kind: ExprKind::IfThenElse(Box::new([cond, then_, else_])),
1751 node_id: cx.next_node_id(),
1752 span: cx.mk_span(lo, hi),
1753 };
1754 }
1755 Ok(else_)
1756}
1757
1758fn parse_block(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1760 delimited(cx, Brace, parse_block_expr)
1761}
1762
1763fn parse_block_expr(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1765 let lo = cx.lo();
1766 let decls = repeat_while(cx, kw::Let, parse_let_decl)?;
1767 let body = parse_expr(cx, true)?;
1768 let hi = cx.hi();
1769
1770 if decls.is_empty() {
1771 Ok(body)
1772 } else {
1773 let kind = ExprKind::Block(decls, Box::new(body));
1774 Ok(Expr { kind, node_id: cx.next_node_id(), span: cx.mk_span(lo, hi) })
1775 }
1776}
1777
1778fn parse_let_decl(cx: &mut ParseCtxt) -> ParseResult<LetDecl> {
1780 cx.expect(kw::Let)?;
1781 let param = parse_refine_param(cx, RequireSort::Maybe)?;
1782 cx.expect(token::Eq)?;
1783 let init = parse_expr(cx, true)?;
1784 cx.expect(token::Semi)?;
1785 Ok(LetDecl { param, init })
1786}
1787
1788fn parse_lit(cx: &mut ParseCtxt) -> ParseResult<Expr> {
1792 if let Token { kind: token::Literal(lit), lo, hi } = cx.at(0) {
1793 cx.advance();
1794 Ok(Expr {
1795 kind: ExprKind::Literal(lit),
1796 node_id: cx.next_node_id(),
1797 span: cx.mk_span(lo, hi),
1798 })
1799 } else {
1800 Err(cx.unexpected_token(vec![AnyLit.expected()]))
1801 }
1802}
1803
1804fn parse_ident(cx: &mut ParseCtxt) -> ParseResult<Ident> {
1805 if let Token { kind: token::Ident(name, is_raw), lo, hi } = cx.at(0)
1806 && (!cx.is_reserved(name) || is_raw == IdentKind::Raw)
1807 {
1808 cx.advance();
1809 return Ok(Ident { name, span: cx.mk_span(lo, hi) });
1810 }
1811 Err(cx.unexpected_token(vec![NonReserved.expected()]))
1812}
1813
1814fn parse_int<T: FromStr>(cx: &mut ParseCtxt) -> ParseResult<T> {
1815 if let token::Literal(lit) = cx.at(0).kind
1816 && let Lit { kind: LitKind::Integer, symbol, suffix: None, .. } = lit
1817 && let Ok(value) = symbol.as_str().parse::<T>()
1818 {
1819 cx.advance();
1820 return Ok(value);
1821 }
1822
1823 Err(cx.unexpected_token(vec![Expected::Str(std::any::type_name::<T>())]))
1824}
1825
1826fn parse_sort(cx: &mut ParseCtxt) -> ParseResult<Sort> {
1832 if cx.peek(token::OpenParen) {
1833 let inputs = parens(cx, Comma, parse_base_sort)?;
1835 if cx.advance_if(token::RArrow) {
1836 let output = parse_base_sort(cx)?;
1838 Ok(Sort::Func { inputs, output })
1839 } else {
1840 Ok(Sort::Base(BaseSort::Tuple(inputs)))
1842 }
1843 } else {
1844 let bsort = parse_base_sort(cx)?;
1845 if cx.advance_if(token::RArrow) {
1846 let output = parse_base_sort(cx)?;
1848 Ok(Sort::Func { inputs: vec![bsort], output })
1849 } else {
1850 Ok(Sort::Base(bsort))
1852 }
1853 }
1854}
1855
1856fn parse_base_sort(cx: &mut ParseCtxt) -> ParseResult<BaseSort> {
1864 if cx.advance_if(kw::Bitvec) {
1865 cx.expect(LAngle)?;
1867 let len = parse_int(cx)?;
1868 cx.expect(RAngle)?;
1869 Ok(BaseSort::BitVec(len))
1870 } else if cx.peek(token::OpenParen) {
1871 let sorts = parens(cx, Comma, parse_base_sort)?;
1873 Ok(BaseSort::Tuple(sorts))
1874 } else if cx.advance_if(LAngle) {
1875 let qself = parse_type(cx)?;
1877 cx.expect(kw::As)?;
1878 let mut path = parse_path(cx)?;
1879 cx.expect(RAngle)?;
1880 cx.expect(token::PathSep)?;
1881 path.segments.push(parse_segment(cx)?);
1882 Ok(BaseSort::SortOf(Box::new(qself), path))
1883 } else {
1884 let segments = sep1(cx, token::PathSep, parse_ident)?;
1886 let args = opt_angle(cx, Comma, parse_base_sort)?;
1887 let path = SortPath { segments, args, node_id: cx.next_node_id() };
1888 Ok(BaseSort::Path(path))
1889 }
1890}
1891
1892#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
1894enum Precedence {
1895 Iff,
1897 Implies,
1899 Or,
1901 And,
1903 Compare,
1905 BitOr,
1907 BitXor,
1909 BitAnd,
1911 Shift,
1913 Sum,
1915 Product,
1917 Prefix,
1919}
1920
1921enum Associativity {
1922 Right,
1923 Left,
1924 None,
1925}
1926
1927impl Precedence {
1928 const MIN: Self = Precedence::Iff;
1929
1930 fn of_binop(op: &BinOp) -> Precedence {
1931 match op {
1932 BinOp::Iff => Precedence::Iff,
1933 BinOp::Imp => Precedence::Implies,
1934 BinOp::Or => Precedence::Or,
1935 BinOp::And => Precedence::And,
1936 BinOp::Eq | BinOp::Ne | BinOp::Gt | BinOp::Ge | BinOp::Lt | BinOp::Le => {
1937 Precedence::Compare
1938 }
1939 BinOp::BitOr => Precedence::BitOr,
1940 BinOp::BitXor => Precedence::BitXor,
1941 BinOp::BitAnd => Precedence::BitAnd,
1942 BinOp::BitShl | BinOp::BitShr => Precedence::Shift,
1943 BinOp::Add | BinOp::Sub => Precedence::Sum,
1944 BinOp::Mul | BinOp::Div | BinOp::Mod => Precedence::Product,
1945 }
1946 }
1947
1948 fn next(self) -> Precedence {
1949 match self {
1950 Precedence::Iff => Precedence::Implies,
1951 Precedence::Implies => Precedence::Or,
1952 Precedence::Or => Precedence::And,
1953 Precedence::And => Precedence::Compare,
1954 Precedence::Compare => Precedence::BitOr,
1955 Precedence::BitOr => Precedence::BitXor,
1956 Precedence::BitXor => Precedence::BitAnd,
1957 Precedence::BitAnd => Precedence::Shift,
1958 Precedence::Shift => Precedence::Sum,
1959 Precedence::Sum => Precedence::Product,
1960 Precedence::Product => Precedence::Prefix,
1961 Precedence::Prefix => Precedence::Prefix,
1962 }
1963 }
1964
1965 fn associativity(self) -> Associativity {
1966 match self {
1967 Precedence::Or
1968 | Precedence::And
1969 | Precedence::BitOr
1970 | Precedence::BitXor
1971 | Precedence::BitAnd
1972 | Precedence::Shift
1973 | Precedence::Sum
1974 | Precedence::Product => Associativity::Left,
1975 Precedence::Compare | Precedence::Iff => Associativity::None,
1976 Precedence::Implies | Precedence::Prefix => Associativity::Right,
1977 }
1978 }
1979}