1use core::mem;
4use core::ops::{Bound, ControlFlow};
5
6use ast::mut_visit::{self, MutVisitor};
7use ast::token::IdentIsRaw;
8use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered};
9use rustc_ast::ptr::P;
10use rustc_ast::token::{self, Delimiter, Token, TokenKind};
11use rustc_ast::tokenstream::TokenTree;
12use rustc_ast::util::case::Case;
13use rustc_ast::util::classify;
14use rustc_ast::util::parser::{AssocOp, ExprPrecedence, Fixity, prec_let_scrutinee_needs_par};
15use rustc_ast::visit::{Visitor, walk_expr};
16use rustc_ast::{
17 self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy,
18 ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall,
19 MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind,
20};
21use rustc_ast_pretty::pprust;
22use rustc_data_structures::stack::ensure_sufficient_stack;
23use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic};
24use rustc_lexer::unescape::unescape_char;
25use rustc_macros::Subdiagnostic;
26use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error};
27use rustc_session::lint::BuiltinLintDiag;
28use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
29use rustc_span::source_map::{self, Spanned};
30use rustc_span::{BytePos, ErrorGuaranteed, Ident, Pos, Span, Symbol, kw, sym};
31use thin_vec::{ThinVec, thin_vec};
32use tracing::instrument;
33
34use super::diagnostics::SnapshotParser;
35use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma};
36use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
37use super::{
38 AttrWrapper, BlockMode, ClosureSpans, ExpTokenPair, ForceCollect, Parser, PathStyle,
39 Restrictions, SemiColonMode, SeqSep, TokenType, Trailing, UsePreAttrPos,
40};
41use crate::{errors, exp, maybe_recover_from_interpolated_ty_qpath};
42
43#[derive(Debug)]
44pub(super) enum DestructuredFloat {
45 Single(Symbol, Span),
47 TrailingDot(Symbol, Span, Span),
49 MiddleDot(Symbol, Span, Span, Symbol, Span),
51 Error,
53}
54
55impl<'a> Parser<'a> {
56 #[inline]
58 pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> {
59 self.current_closure.take();
60
61 let attrs = self.parse_outer_attributes()?;
62 self.parse_expr_res(Restrictions::empty(), attrs).map(|res| res.0)
63 }
64
65 pub fn parse_expr_force_collect(&mut self) -> PResult<'a, P<Expr>> {
67 self.current_closure.take();
68
69 let pre_attr_pos = self.collect_pos();
74 let attrs = self.parse_outer_attributes()?;
75 self.collect_tokens(
76 Some(pre_attr_pos),
77 AttrWrapper::empty(),
78 ForceCollect::Yes,
79 |this, _empty_attrs| {
80 let (expr, is_assoc) = this.parse_expr_res(Restrictions::empty(), attrs)?;
81 let use_pre_attr_pos =
82 if is_assoc { UsePreAttrPos::Yes } else { UsePreAttrPos::No };
83 Ok((expr, Trailing::No, use_pre_attr_pos))
84 },
85 )
86 }
87
88 pub fn parse_expr_anon_const(&mut self) -> PResult<'a, AnonConst> {
89 self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value })
90 }
91
92 fn parse_expr_catch_underscore(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> {
93 let attrs = self.parse_outer_attributes()?;
94 match self.parse_expr_res(restrictions, attrs) {
95 Ok((expr, _)) => Ok(expr),
96 Err(err) => match self.token.ident() {
97 Some((Ident { name: kw::Underscore, .. }, IdentIsRaw::No))
98 if self.may_recover() && self.look_ahead(1, |t| t == &token::Comma) =>
99 {
100 let guar = err.emit();
102 self.bump();
103 Ok(self.mk_expr(self.prev_token.span, ExprKind::Err(guar)))
104 }
105 _ => Err(err),
106 },
107 }
108 }
109
110 fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<P<Expr>>> {
112 self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore(Restrictions::empty()))
113 .map(|(r, _)| r)
114 }
115
116 #[inline]
118 pub(super) fn parse_expr_res(
119 &mut self,
120 r: Restrictions,
121 attrs: AttrWrapper,
122 ) -> PResult<'a, (P<Expr>, bool)> {
123 self.with_res(r, |this| this.parse_expr_assoc_with(Bound::Unbounded, attrs))
124 }
125
126 pub(super) fn parse_expr_assoc_with(
130 &mut self,
131 min_prec: Bound<ExprPrecedence>,
132 attrs: AttrWrapper,
133 ) -> PResult<'a, (P<Expr>, bool)> {
134 let lhs = if self.token.is_range_separator() {
135 return self.parse_expr_prefix_range(attrs).map(|res| (res, false));
136 } else {
137 self.parse_expr_prefix(attrs)?
138 };
139 self.parse_expr_assoc_rest_with(min_prec, false, lhs)
140 }
141
142 pub(super) fn parse_expr_assoc_rest_with(
146 &mut self,
147 min_prec: Bound<ExprPrecedence>,
148 starts_stmt: bool,
149 mut lhs: P<Expr>,
150 ) -> PResult<'a, (P<Expr>, bool)> {
151 let mut parsed_something = false;
152 if !self.should_continue_as_assoc_expr(&lhs) {
153 return Ok((lhs, parsed_something));
154 }
155
156 self.expected_token_types.insert(TokenType::Operator);
157 while let Some(op) = self.check_assoc_op() {
158 let lhs_span = self.interpolated_or_expr_span(&lhs);
159 let cur_op_span = self.token.span;
160 let restrictions = if op.node.is_assign_like() {
161 self.restrictions & Restrictions::NO_STRUCT_LITERAL
162 } else {
163 self.restrictions
164 };
165 let prec = op.node.precedence();
166 if match min_prec {
167 Bound::Included(min_prec) => prec < min_prec,
168 Bound::Excluded(min_prec) => prec <= min_prec,
169 Bound::Unbounded => false,
170 } {
171 break;
172 }
173 if self.token == token::DotDotDot && op.node == AssocOp::DotDotEq {
175 self.err_dotdotdot_syntax(self.token.span);
176 }
177
178 if self.token == token::LArrow {
179 self.err_larrow_operator(self.token.span);
180 }
181
182 parsed_something = true;
183 self.bump();
184 if op.node.is_comparison() {
185 if let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? {
186 return Ok((expr, parsed_something));
187 }
188 }
189
190 if (op.node == AssocOp::Equal || op.node == AssocOp::NotEqual)
192 && self.token == token::Eq
193 && self.prev_token.span.hi() == self.token.span.lo()
194 {
195 let sp = op.span.to(self.token.span);
196 let sugg = match op.node {
197 AssocOp::Equal => "==",
198 AssocOp::NotEqual => "!=",
199 _ => unreachable!(),
200 }
201 .into();
202 let invalid = format!("{sugg}=");
203 self.dcx().emit_err(errors::InvalidComparisonOperator {
204 span: sp,
205 invalid: invalid.clone(),
206 sub: errors::InvalidComparisonOperatorSub::Correctable {
207 span: sp,
208 invalid,
209 correct: sugg,
210 },
211 });
212 self.bump();
213 }
214
215 if op.node == AssocOp::Less
217 && self.token == token::Gt
218 && self.prev_token.span.hi() == self.token.span.lo()
219 {
220 let sp = op.span.to(self.token.span);
221 self.dcx().emit_err(errors::InvalidComparisonOperator {
222 span: sp,
223 invalid: "<>".into(),
224 sub: errors::InvalidComparisonOperatorSub::Correctable {
225 span: sp,
226 invalid: "<>".into(),
227 correct: "!=".into(),
228 },
229 });
230 self.bump();
231 }
232
233 if op.node == AssocOp::LessEqual
235 && self.token == token::Gt
236 && self.prev_token.span.hi() == self.token.span.lo()
237 {
238 let sp = op.span.to(self.token.span);
239 self.dcx().emit_err(errors::InvalidComparisonOperator {
240 span: sp,
241 invalid: "<=>".into(),
242 sub: errors::InvalidComparisonOperatorSub::Spaceship(sp),
243 });
244 self.bump();
245 }
246
247 if self.prev_token == token::BinOp(token::Plus)
248 && self.token == token::BinOp(token::Plus)
249 && self.prev_token.span.between(self.token.span).is_empty()
250 {
251 let op_span = self.prev_token.span.to(self.token.span);
252 self.bump();
254 lhs = self.recover_from_postfix_increment(lhs, op_span, starts_stmt)?;
255 continue;
256 }
257
258 if self.prev_token == token::BinOp(token::Minus)
259 && self.token == token::BinOp(token::Minus)
260 && self.prev_token.span.between(self.token.span).is_empty()
261 && !self.look_ahead(1, |tok| tok.can_begin_expr())
262 {
263 let op_span = self.prev_token.span.to(self.token.span);
264 self.bump();
266 lhs = self.recover_from_postfix_decrement(lhs, op_span, starts_stmt)?;
267 continue;
268 }
269
270 let op = op.node;
271 if op == AssocOp::As {
273 lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?;
274 continue;
275 } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
276 lhs = self.parse_expr_range(prec, lhs, op, cur_op_span)?;
279 break;
280 }
281
282 let min_prec = match op.fixity() {
283 Fixity::Right => Bound::Included(prec),
284 Fixity::Left | Fixity::None => Bound::Excluded(prec),
285 };
286 let (rhs, _) = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| {
287 let attrs = this.parse_outer_attributes()?;
288 this.parse_expr_assoc_with(min_prec, attrs)
289 })?;
290
291 let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
292 lhs = match op {
293 AssocOp::Add
294 | AssocOp::Subtract
295 | AssocOp::Multiply
296 | AssocOp::Divide
297 | AssocOp::Modulus
298 | AssocOp::LAnd
299 | AssocOp::LOr
300 | AssocOp::BitXor
301 | AssocOp::BitAnd
302 | AssocOp::BitOr
303 | AssocOp::ShiftLeft
304 | AssocOp::ShiftRight
305 | AssocOp::Equal
306 | AssocOp::Less
307 | AssocOp::LessEqual
308 | AssocOp::NotEqual
309 | AssocOp::Greater
310 | AssocOp::GreaterEqual => {
311 let ast_op = op.to_ast_binop().unwrap();
312 let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs);
313 self.mk_expr(span, binary)
314 }
315 AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs, cur_op_span)),
316 AssocOp::AssignOp(k) => {
317 let aop = match k {
318 token::Plus => BinOpKind::Add,
319 token::Minus => BinOpKind::Sub,
320 token::Star => BinOpKind::Mul,
321 token::Slash => BinOpKind::Div,
322 token::Percent => BinOpKind::Rem,
323 token::Caret => BinOpKind::BitXor,
324 token::And => BinOpKind::BitAnd,
325 token::Or => BinOpKind::BitOr,
326 token::Shl => BinOpKind::Shl,
327 token::Shr => BinOpKind::Shr,
328 };
329 let aopexpr = self.mk_assign_op(source_map::respan(cur_op_span, aop), lhs, rhs);
330 self.mk_expr(span, aopexpr)
331 }
332 AssocOp::As | AssocOp::DotDot | AssocOp::DotDotEq => {
333 self.dcx().span_bug(span, "AssocOp should have been handled by special case")
334 }
335 };
336 }
337
338 Ok((lhs, parsed_something))
339 }
340
341 fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool {
342 match (self.expr_is_complete(lhs), AssocOp::from_token(&self.token)) {
343 (true, None) => false,
346 (false, _) => true, (true, Some(AssocOp::Multiply)) | (true, Some(AssocOp::Subtract)) | (true, Some(AssocOp::Add)) | (true, Some(AssocOp::LAnd)) | (true, Some(AssocOp::LOr)) | (true, Some(AssocOp::BitOr)) => {
357 let sp = self.psess.source_map().start_point(self.token.span);
364 self.psess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
365 false
366 }
367 (true, Some(op)) if !op.can_continue_expr_unambiguously() => false,
368 (true, Some(_)) => {
369 self.error_found_expr_would_be_stmt(lhs);
370 true
371 }
372 }
373 }
374
375 fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
379 self.dcx().emit_err(errors::FoundExprWouldBeStmt {
380 span: self.token.span,
381 token: self.token.clone(),
382 suggestion: ExprParenthesesNeeded::surrounding(lhs.span),
383 });
384 }
385
386 pub(super) fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
391 let (op, span) = match (AssocOp::from_token(&self.token), self.token.ident()) {
392 (
394 Some(
395 AssocOp::ShiftRight
396 | AssocOp::Greater
397 | AssocOp::GreaterEqual
398 | AssocOp::AssignOp(token::BinOpToken::Shr),
399 ),
400 _,
401 ) if self.restrictions.contains(Restrictions::CONST_EXPR) => {
402 return None;
403 }
404 (
406 Some(
407 AssocOp::Assign
408 | AssocOp::AssignOp(_)
409 | AssocOp::BitOr
410 | AssocOp::DotDot
411 | AssocOp::DotDotEq,
412 ),
413 _,
414 ) if self.restrictions.contains(Restrictions::IS_PAT) => {
415 return None;
416 }
417 (Some(op), _) => (op, self.token.span),
418 (None, Some((Ident { name: sym::and, span }, IdentIsRaw::No)))
419 if self.may_recover() =>
420 {
421 self.dcx().emit_err(errors::InvalidLogicalOperator {
422 span: self.token.span,
423 incorrect: "and".into(),
424 sub: errors::InvalidLogicalOperatorSub::Conjunction(self.token.span),
425 });
426 (AssocOp::LAnd, span)
427 }
428 (None, Some((Ident { name: sym::or, span }, IdentIsRaw::No))) if self.may_recover() => {
429 self.dcx().emit_err(errors::InvalidLogicalOperator {
430 span: self.token.span,
431 incorrect: "or".into(),
432 sub: errors::InvalidLogicalOperatorSub::Disjunction(self.token.span),
433 });
434 (AssocOp::LOr, span)
435 }
436 _ => return None,
437 };
438 Some(source_map::respan(span, op))
439 }
440
441 fn expr_is_complete(&self, e: &Expr) -> bool {
443 self.restrictions.contains(Restrictions::STMT_EXPR) && classify::expr_is_complete(e)
444 }
445
446 fn parse_expr_range(
449 &mut self,
450 prec: ExprPrecedence,
451 lhs: P<Expr>,
452 op: AssocOp,
453 cur_op_span: Span,
454 ) -> PResult<'a, P<Expr>> {
455 let rhs = if self.is_at_start_of_range_notation_rhs() {
456 let maybe_lt = self.token.clone();
457 let attrs = self.parse_outer_attributes()?;
458 Some(
459 self.parse_expr_assoc_with(Bound::Excluded(prec), attrs)
460 .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?
461 .0,
462 )
463 } else {
464 None
465 };
466 let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
467 let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
468 let limits =
469 if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
470 let range = self.mk_range(Some(lhs), rhs, limits);
471 Ok(self.mk_expr(span, range))
472 }
473
474 fn is_at_start_of_range_notation_rhs(&self) -> bool {
475 if self.token.can_begin_expr() {
476 if self.token == token::OpenDelim(Delimiter::Brace) {
478 return !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
479 }
480 true
481 } else {
482 false
483 }
484 }
485
486 fn parse_expr_prefix_range(&mut self, attrs: AttrWrapper) -> PResult<'a, P<Expr>> {
488 if !attrs.is_empty() {
489 let err = errors::DotDotRangeAttribute { span: self.token.span };
490 self.dcx().emit_err(err);
491 }
492
493 if self.token == token::DotDotDot {
495 self.err_dotdotdot_syntax(self.token.span);
496 }
497
498 debug_assert!(
499 self.token.is_range_separator(),
500 "parse_prefix_range_expr: token {:?} is not DotDot/DotDotEq",
501 self.token
502 );
503
504 let limits = match self.token.kind {
505 token::DotDot => RangeLimits::HalfOpen,
506 _ => RangeLimits::Closed,
507 };
508 let op = AssocOp::from_token(&self.token);
509 let attrs = self.parse_outer_attributes()?;
510 self.collect_tokens_for_expr(attrs, |this, attrs| {
511 let lo = this.token.span;
512 let maybe_lt = this.look_ahead(1, |t| t.clone());
513 this.bump();
514 let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
515 let attrs = this.parse_outer_attributes()?;
517 this.parse_expr_assoc_with(Bound::Excluded(op.unwrap().precedence()), attrs)
518 .map(|(x, _)| (lo.to(x.span), Some(x)))
519 .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))?
520 } else {
521 (lo, None)
522 };
523 let range = this.mk_range(None, opt_end, limits);
524 Ok(this.mk_expr_with_attrs(span, range, attrs))
525 })
526 }
527
528 fn parse_expr_prefix(&mut self, attrs: AttrWrapper) -> PResult<'a, P<Expr>> {
530 let lo = self.token.span;
531
532 macro_rules! make_it {
533 ($this:ident, $attrs:expr, |this, _| $body:expr) => {
534 $this.collect_tokens_for_expr($attrs, |$this, attrs| {
535 let (hi, ex) = $body?;
536 Ok($this.mk_expr_with_attrs(lo.to(hi), ex, attrs))
537 })
538 };
539 }
540
541 let this = self;
542
543 match this.token.uninterpolate().kind {
545 token::Not => make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Not)),
547 token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)),
549 token::BinOp(token::Minus) => {
551 make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Neg))
552 }
553 token::BinOp(token::Star) => {
555 make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Deref))
556 }
557 token::BinOp(token::And) | token::AndAnd => {
559 make_it!(this, attrs, |this, _| this.parse_expr_borrow(lo))
560 }
561 token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
563 let mut err = errors::LeadingPlusNotSupported {
564 span: lo,
565 remove_plus: None,
566 add_parentheses: None,
567 };
568
569 if let Some(sp) = this.psess.ambiguous_block_expr_parse.borrow().get(&lo) {
571 err.add_parentheses = Some(ExprParenthesesNeeded::surrounding(*sp));
572 } else {
573 err.remove_plus = Some(lo);
574 }
575 this.dcx().emit_err(err);
576
577 this.bump();
578 let attrs = this.parse_outer_attributes()?;
579 this.parse_expr_prefix(attrs)
580 }
581 token::BinOp(token::Plus)
583 if this.look_ahead(1, |t| *t == token::BinOp(token::Plus)) =>
584 {
585 let starts_stmt = this.prev_token == token::Semi
586 || this.prev_token == token::CloseDelim(Delimiter::Brace);
587 let pre_span = this.token.span.to(this.look_ahead(1, |t| t.span));
588 this.bump();
590 this.bump();
591
592 let operand_expr = this.parse_expr_dot_or_call(attrs)?;
593 this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt)
594 }
595 token::Ident(..) if this.token.is_keyword(kw::Box) => {
596 make_it!(this, attrs, |this, _| this.parse_expr_box(lo))
597 }
598 token::Ident(..) if this.may_recover() && this.is_mistaken_not_ident_negation() => {
599 make_it!(this, attrs, |this, _| this.recover_not_expr(lo))
600 }
601 _ => return this.parse_expr_dot_or_call(attrs),
602 }
603 }
604
605 fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
606 self.bump();
607 let attrs = self.parse_outer_attributes()?;
608 let expr = self.parse_expr_prefix(attrs)?;
609 let span = self.interpolated_or_expr_span(&expr);
610 Ok((lo.to(span), expr))
611 }
612
613 fn parse_expr_unary(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> {
614 let (span, expr) = self.parse_expr_prefix_common(lo)?;
615 Ok((span, self.mk_unary(op, expr)))
616 }
617
618 fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
620 self.dcx().emit_err(errors::TildeAsUnaryOperator(lo));
621
622 self.parse_expr_unary(lo, UnOp::Not)
623 }
624
625 fn parse_expr_box(&mut self, box_kw: Span) -> PResult<'a, (Span, ExprKind)> {
628 let (span, expr) = self.parse_expr_prefix_common(box_kw)?;
629 let box_kw_and_lo = box_kw.until(self.interpolated_or_expr_span(&expr));
631 let hi = span.shrink_to_hi();
632 let sugg = errors::AddBoxNew { box_kw_and_lo, hi };
633 let guar = self.dcx().emit_err(errors::BoxSyntaxRemoved { span, sugg });
634 Ok((span, ExprKind::Err(guar)))
635 }
636
637 fn is_mistaken_not_ident_negation(&self) -> bool {
638 let token_cannot_continue_expr = |t: &Token| match t.uninterpolate().kind {
639 token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw),
642 token::Literal(..) | token::Pound => true,
643 _ => t.is_whole_expr(),
644 };
645 self.token.is_ident_named(sym::not) && self.look_ahead(1, token_cannot_continue_expr)
646 }
647
648 fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
650 let negated_token = self.look_ahead(1, |t| t.clone());
651
652 let sub_diag = if negated_token.is_numeric_lit() {
653 errors::NotAsNegationOperatorSub::SuggestNotBitwise
654 } else if negated_token.is_bool_lit() {
655 errors::NotAsNegationOperatorSub::SuggestNotLogical
656 } else {
657 errors::NotAsNegationOperatorSub::SuggestNotDefault
658 };
659
660 self.dcx().emit_err(errors::NotAsNegationOperator {
661 negated: negated_token.span,
662 negated_desc: super::token_descr(&negated_token),
663 sub: sub_diag(
666 self.psess.source_map().span_until_non_whitespace(lo.to(negated_token.span)),
667 ),
668 });
669
670 self.parse_expr_unary(lo, UnOp::Not)
671 }
672
673 fn interpolated_or_expr_span(&self, expr: &Expr) -> Span {
675 match self.prev_token.kind {
676 TokenKind::NtIdent(..) | TokenKind::NtLifetime(..) | TokenKind::Interpolated(..) => {
677 self.prev_token.span
678 }
679 _ => expr.span,
680 }
681 }
682
683 fn parse_assoc_op_cast(
684 &mut self,
685 lhs: P<Expr>,
686 lhs_span: Span,
687 expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind,
688 ) -> PResult<'a, P<Expr>> {
689 let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| {
690 this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, rhs.span), expr_kind(lhs, rhs))
691 };
692
693 let parser_snapshot_before_type = self.clone();
696 let cast_expr = match self.parse_as_cast_ty() {
697 Ok(rhs) => mk_expr(self, lhs, rhs),
698 Err(type_err) => {
699 if !self.may_recover() {
700 return Err(type_err);
701 }
702
703 let parser_snapshot_after_type = mem::replace(self, parser_snapshot_before_type);
707
708 match (&lhs.kind, &self.token.kind) {
710 (
711 ExprKind::Path(None, ast::Path { segments, .. }),
713 token::Ident(kw::For | kw::Loop | kw::While, IdentIsRaw::No),
714 ) if let [segment] = segments.as_slice() => {
715 let snapshot = self.create_snapshot_for_diagnostic();
716 let label = Label {
717 ident: Ident::from_str_and_span(
718 &format!("'{}", segment.ident),
719 segment.ident.span,
720 ),
721 };
722 match self.parse_expr_labeled(label, false) {
723 Ok(expr) => {
724 type_err.cancel();
725 self.dcx().emit_err(errors::MalformedLoopLabel {
726 span: label.ident.span,
727 suggestion: label.ident.span.shrink_to_lo(),
728 });
729 return Ok(expr);
730 }
731 Err(err) => {
732 err.cancel();
733 self.restore_snapshot(snapshot);
734 }
735 }
736 }
737 _ => {}
738 }
739
740 match self.parse_path(PathStyle::Expr) {
741 Ok(path) => {
742 let span_after_type = parser_snapshot_after_type.token.span;
743 let expr = mk_expr(
744 self,
745 lhs,
746 self.mk_ty(path.span, TyKind::Path(None, path.clone())),
747 );
748
749 let args_span = self.look_ahead(1, |t| t.span).to(span_after_type);
750 let suggestion = errors::ComparisonOrShiftInterpretedAsGenericSugg {
751 left: expr.span.shrink_to_lo(),
752 right: expr.span.shrink_to_hi(),
753 };
754
755 match self.token.kind {
756 token::Lt => {
757 self.dcx().emit_err(errors::ComparisonInterpretedAsGeneric {
758 comparison: self.token.span,
759 r#type: path,
760 args: args_span,
761 suggestion,
762 })
763 }
764 token::BinOp(token::Shl) => {
765 self.dcx().emit_err(errors::ShiftInterpretedAsGeneric {
766 shift: self.token.span,
767 r#type: path,
768 args: args_span,
769 suggestion,
770 })
771 }
772 _ => {
773 *self = parser_snapshot_after_type;
778 return Err(type_err);
779 }
780 };
781
782 type_err.cancel();
784
785 expr
787 }
788 Err(path_err) => {
789 path_err.cancel();
791 *self = parser_snapshot_after_type;
792 return Err(type_err);
793 }
794 }
795 }
796 };
797
798 let span = cast_expr.span;
804
805 let with_postfix = self.parse_expr_dot_or_call_with(AttrVec::new(), cast_expr, span)?;
806
807 if !matches!(with_postfix.kind, ExprKind::Cast(_, _)) {
810 let msg = format!(
811 "cast cannot be followed by {}",
812 match with_postfix.kind {
813 ExprKind::Index(..) => "indexing",
814 ExprKind::Try(_) => "`?`",
815 ExprKind::Field(_, _) => "a field access",
816 ExprKind::MethodCall(_) => "a method call",
817 ExprKind::Call(_, _) => "a function call",
818 ExprKind::Await(_, _) => "`.await`",
819 ExprKind::Match(_, _, MatchKind::Postfix) => "a postfix match",
820 ExprKind::Err(_) => return Ok(with_postfix),
821 _ => unreachable!("parse_dot_or_call_expr_with_ shouldn't produce this"),
822 }
823 );
824 let mut err = self.dcx().struct_span_err(span, msg);
825
826 let suggest_parens = |err: &mut Diag<'_>| {
827 let suggestions = vec![
828 (span.shrink_to_lo(), "(".to_string()),
829 (span.shrink_to_hi(), ")".to_string()),
830 ];
831 err.multipart_suggestion(
832 "try surrounding the expression in parentheses",
833 suggestions,
834 Applicability::MachineApplicable,
835 );
836 };
837
838 suggest_parens(&mut err);
839
840 err.emit();
841 };
842 Ok(with_postfix)
843 }
844
845 fn parse_expr_borrow(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
847 self.expect_and()?;
848 let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
849 let lifetime = has_lifetime.then(|| self.expect_lifetime()); let (borrow_kind, mutbl) = self.parse_borrow_modifiers();
851 let attrs = self.parse_outer_attributes()?;
852 let expr = if self.token.is_range_separator() {
853 self.parse_expr_prefix_range(attrs)
854 } else {
855 self.parse_expr_prefix(attrs)
856 }?;
857 let hi = self.interpolated_or_expr_span(&expr);
858 let span = lo.to(hi);
859 if let Some(lt) = lifetime {
860 self.error_remove_borrow_lifetime(span, lt.ident.span.until(expr.span));
861 }
862 Ok((span, ExprKind::AddrOf(borrow_kind, mutbl, expr)))
863 }
864
865 fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
866 self.dcx().emit_err(errors::LifetimeInBorrowExpression { span, lifetime_span: lt_span });
867 }
868
869 fn parse_borrow_modifiers(&mut self) -> (ast::BorrowKind, ast::Mutability) {
871 if self.check_keyword(exp!(Raw)) && self.look_ahead(1, Token::is_mutability) {
872 let found_raw = self.eat_keyword(exp!(Raw));
874 assert!(found_raw);
875 let mutability = self.parse_const_or_mut().unwrap();
876 (ast::BorrowKind::Raw, mutability)
877 } else {
878 (ast::BorrowKind::Ref, self.parse_mutability())
880 }
881 }
882
883 fn parse_expr_dot_or_call(&mut self, attrs: AttrWrapper) -> PResult<'a, P<Expr>> {
885 self.collect_tokens_for_expr(attrs, |this, attrs| {
886 let base = this.parse_expr_bottom()?;
887 let span = this.interpolated_or_expr_span(&base);
888 this.parse_expr_dot_or_call_with(attrs, base, span)
889 })
890 }
891
892 pub(super) fn parse_expr_dot_or_call_with(
893 &mut self,
894 mut attrs: ast::AttrVec,
895 mut e: P<Expr>,
896 lo: Span,
897 ) -> PResult<'a, P<Expr>> {
898 let mut res = ensure_sufficient_stack(|| {
899 loop {
900 let has_question =
901 if self.prev_token == TokenKind::Ident(kw::Return, IdentIsRaw::No) {
902 self.eat_noexpect(&token::Question)
905 } else {
906 self.eat(exp!(Question))
907 };
908 if has_question {
909 e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e));
911 continue;
912 }
913 let has_dot = if self.prev_token == TokenKind::Ident(kw::Return, IdentIsRaw::No) {
914 self.eat_noexpect(&token::Dot)
917 } else if self.token == TokenKind::RArrow && self.may_recover() {
918 self.bump();
920 let span = self.prev_token.span;
921 self.dcx().emit_err(errors::ExprRArrowCall { span });
922 true
923 } else {
924 self.eat(exp!(Dot))
925 };
926 if has_dot {
927 e = self.parse_dot_suffix_expr(lo, e)?;
929 continue;
930 }
931 if self.expr_is_complete(&e) {
932 return Ok(e);
933 }
934 e = match self.token.kind {
935 token::OpenDelim(Delimiter::Parenthesis) => self.parse_expr_fn_call(lo, e),
936 token::OpenDelim(Delimiter::Bracket) => self.parse_expr_index(lo, e)?,
937 _ => return Ok(e),
938 }
939 }
940 });
941
942 if !attrs.is_empty()
945 && let Ok(expr) = &mut res
946 {
947 mem::swap(&mut expr.attrs, &mut attrs);
948 expr.attrs.extend(attrs)
949 }
950 res
951 }
952
953 pub(super) fn parse_dot_suffix_expr(
954 &mut self,
955 lo: Span,
956 base: P<Expr>,
957 ) -> PResult<'a, P<Expr>> {
958 match self.token.uninterpolate().kind {
961 token::Ident(..) => self.parse_dot_suffix(base, lo),
962 token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => {
963 let ident_span = self.token.span;
964 self.bump();
965 Ok(self.mk_expr_tuple_field_access(lo, ident_span, base, symbol, suffix))
966 }
967 token::Literal(token::Lit { kind: token::Float, symbol, suffix }) => {
968 Ok(match self.break_up_float(symbol, self.token.span) {
969 DestructuredFloat::Single(sym, _sp) => {
971 let ident_span = self.token.span;
975 self.bump();
976 self.mk_expr_tuple_field_access(lo, ident_span, base, sym, suffix)
977 }
978 DestructuredFloat::TrailingDot(sym, ident_span, dot_span) => {
980 assert!(suffix.is_none());
984 self.token = Token::new(token::Ident(sym, IdentIsRaw::No), ident_span);
985 self.bump_with((Token::new(token::Dot, dot_span), self.token_spacing));
986 self.mk_expr_tuple_field_access(lo, ident_span, base, sym, None)
987 }
988 DestructuredFloat::MiddleDot(
990 sym1,
991 ident1_span,
992 _dot_span,
993 sym2,
994 ident2_span,
995 ) => {
996 let next_token2 =
1000 Token::new(token::Ident(sym2, IdentIsRaw::No), ident2_span);
1001 self.bump_with((next_token2, self.token_spacing));
1002 self.bump();
1003 let base1 =
1004 self.mk_expr_tuple_field_access(lo, ident1_span, base, sym1, None);
1005 self.mk_expr_tuple_field_access(lo, ident2_span, base1, sym2, suffix)
1006 }
1007 DestructuredFloat::Error => base,
1008 })
1009 }
1010 _ => {
1011 self.error_unexpected_after_dot();
1012 Ok(base)
1013 }
1014 }
1015 }
1016
1017 fn error_unexpected_after_dot(&self) {
1018 let actual = pprust::token_to_string(&self.token);
1019 let span = self.token.span;
1020 let sm = self.psess.source_map();
1021 let (span, actual) = match (&self.token.kind, self.subparser_name) {
1022 (token::Eof, Some(_)) if let Ok(actual) = sm.span_to_snippet(sm.next_point(span)) => {
1023 (span.shrink_to_hi(), actual.into())
1024 }
1025 _ => (span, actual),
1026 };
1027 self.dcx().emit_err(errors::UnexpectedTokenAfterDot { span, actual });
1028 }
1029
1030 pub(super) fn break_up_float(&self, float: Symbol, span: Span) -> DestructuredFloat {
1041 #[derive(Debug)]
1042 enum FloatComponent {
1043 IdentLike(String),
1044 Punct(char),
1045 }
1046 use FloatComponent::*;
1047
1048 let float_str = float.as_str();
1049 let mut components = Vec::new();
1050 let mut ident_like = String::new();
1051 for c in float_str.chars() {
1052 if c == '_' || c.is_ascii_alphanumeric() {
1053 ident_like.push(c);
1054 } else if matches!(c, '.' | '+' | '-') {
1055 if !ident_like.is_empty() {
1056 components.push(IdentLike(mem::take(&mut ident_like)));
1057 }
1058 components.push(Punct(c));
1059 } else {
1060 panic!("unexpected character in a float token: {c:?}")
1061 }
1062 }
1063 if !ident_like.is_empty() {
1064 components.push(IdentLike(ident_like));
1065 }
1066
1067 let can_take_span_apart =
1071 || self.span_to_snippet(span).as_deref() == Ok(float_str).as_deref();
1072
1073 match &*components {
1074 [IdentLike(i)] => {
1076 DestructuredFloat::Single(Symbol::intern(i), span)
1077 }
1078 [IdentLike(left), Punct('.')] => {
1080 let (left_span, dot_span) = if can_take_span_apart() {
1081 let left_span = span.with_hi(span.lo() + BytePos::from_usize(left.len()));
1082 let dot_span = span.with_lo(left_span.hi());
1083 (left_span, dot_span)
1084 } else {
1085 (span, span)
1086 };
1087 let left = Symbol::intern(left);
1088 DestructuredFloat::TrailingDot(left, left_span, dot_span)
1089 }
1090 [IdentLike(left), Punct('.'), IdentLike(right)] => {
1092 let (left_span, dot_span, right_span) = if can_take_span_apart() {
1093 let left_span = span.with_hi(span.lo() + BytePos::from_usize(left.len()));
1094 let dot_span = span.with_lo(left_span.hi()).with_hi(left_span.hi() + BytePos(1));
1095 let right_span = span.with_lo(dot_span.hi());
1096 (left_span, dot_span, right_span)
1097 } else {
1098 (span, span, span)
1099 };
1100 let left = Symbol::intern(left);
1101 let right = Symbol::intern(right);
1102 DestructuredFloat::MiddleDot(left, left_span, dot_span, right, right_span)
1103 }
1104 [IdentLike(_), Punct('+' | '-')] |
1106 [IdentLike(_), Punct('+' | '-'), IdentLike(_)] |
1108 [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-')] |
1110 [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-'), IdentLike(_)] => {
1112 self.error_unexpected_after_dot();
1114 DestructuredFloat::Error
1115 }
1116 _ => panic!("unexpected components in a float token: {components:?}"),
1117 }
1118 }
1119
1120 fn parse_floating_field_access(&mut self) -> PResult<'a, P<[Ident]>> {
1124 let mut fields = Vec::new();
1125 let mut trailing_dot = None;
1126
1127 loop {
1128 let expr = self.parse_expr()?;
1132 let mut current = &expr;
1133 let start_idx = fields.len();
1134 loop {
1135 match current.kind {
1136 ExprKind::Field(ref left, right) => {
1137 fields.insert(start_idx, right);
1139 trailing_dot = None;
1140 current = left;
1141 }
1142 ExprKind::Index(ref left, ref _right, span) => {
1145 self.dcx().emit_err(errors::ArrayIndexInOffsetOf(span));
1146 current = left;
1147 }
1148 ExprKind::Lit(token::Lit {
1149 kind: token::Float | token::Integer,
1150 symbol,
1151 suffix,
1152 }) => {
1153 if let Some(suffix) = suffix {
1154 self.expect_no_tuple_index_suffix(current.span, suffix);
1155 }
1156 match self.break_up_float(symbol, current.span) {
1157 DestructuredFloat::Single(sym, sp) => {
1159 trailing_dot = None;
1160 fields.insert(start_idx, Ident::new(sym, sp));
1161 }
1162 DestructuredFloat::TrailingDot(sym, sym_span, dot_span) => {
1164 assert!(suffix.is_none());
1165 trailing_dot = Some(dot_span);
1166 fields.insert(start_idx, Ident::new(sym, sym_span));
1167 }
1168 DestructuredFloat::MiddleDot(
1170 symbol1,
1171 span1,
1172 _dot_span,
1173 symbol2,
1174 span2,
1175 ) => {
1176 trailing_dot = None;
1177 fields.insert(start_idx, Ident::new(symbol2, span2));
1178 fields.insert(start_idx, Ident::new(symbol1, span1));
1179 }
1180 DestructuredFloat::Error => {
1181 trailing_dot = None;
1182 fields.insert(start_idx, Ident::new(symbol, self.prev_token.span));
1183 }
1184 }
1185 break;
1186 }
1187 ExprKind::Path(None, Path { ref segments, .. }) => {
1188 match &segments[..] {
1189 [PathSegment { ident, args: None, .. }] => {
1190 trailing_dot = None;
1191 fields.insert(start_idx, *ident)
1192 }
1193 _ => {
1194 self.dcx().emit_err(errors::InvalidOffsetOf(current.span));
1195 break;
1196 }
1197 }
1198 break;
1199 }
1200 _ => {
1201 self.dcx().emit_err(errors::InvalidOffsetOf(current.span));
1202 break;
1203 }
1204 }
1205 }
1206
1207 if matches!(self.token.kind, token::CloseDelim(..) | token::Comma) {
1208 break;
1209 } else if trailing_dot.is_none() {
1210 self.dcx().emit_err(errors::InvalidOffsetOf(self.token.span));
1212 break;
1213 }
1214 }
1215 if let Some(dot) = trailing_dot {
1216 self.dcx().emit_err(errors::InvalidOffsetOf(dot));
1217 }
1218 Ok(fields.into_iter().collect())
1219 }
1220
1221 fn mk_expr_tuple_field_access(
1222 &self,
1223 lo: Span,
1224 ident_span: Span,
1225 base: P<Expr>,
1226 field: Symbol,
1227 suffix: Option<Symbol>,
1228 ) -> P<Expr> {
1229 if let Some(suffix) = suffix {
1230 self.expect_no_tuple_index_suffix(ident_span, suffix);
1231 }
1232 self.mk_expr(lo.to(ident_span), ExprKind::Field(base, Ident::new(field, ident_span)))
1233 }
1234
1235 fn parse_expr_fn_call(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
1237 let snapshot = if self.token == token::OpenDelim(Delimiter::Parenthesis) {
1238 Some((self.create_snapshot_for_diagnostic(), fun.kind.clone()))
1239 } else {
1240 None
1241 };
1242 let open_paren = self.token.span;
1243
1244 let seq = self
1245 .parse_expr_paren_seq()
1246 .map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args)));
1247 match self.maybe_recover_struct_lit_bad_delims(lo, open_paren, seq, snapshot) {
1248 Ok(expr) => expr,
1249 Err(err) => self.recover_seq_parse_error(exp!(OpenParen), exp!(CloseParen), lo, err),
1250 }
1251 }
1252
1253 #[instrument(skip(self, seq, snapshot), level = "trace")]
1256 fn maybe_recover_struct_lit_bad_delims(
1257 &mut self,
1258 lo: Span,
1259 open_paren: Span,
1260 seq: PResult<'a, P<Expr>>,
1261 snapshot: Option<(SnapshotParser<'a>, ExprKind)>,
1262 ) -> PResult<'a, P<Expr>> {
1263 match (self.may_recover(), seq, snapshot) {
1264 (true, Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
1265 snapshot.bump(); match snapshot.parse_struct_fields(path.clone(), false, exp!(CloseParen)) {
1267 Ok((fields, ..)) if snapshot.eat(exp!(CloseParen)) => {
1268 self.restore_snapshot(snapshot);
1271 let close_paren = self.prev_token.span;
1272 let span = lo.to(close_paren);
1273 let fields: Vec<_> =
1275 fields.into_iter().filter(|field| !field.is_shorthand).collect();
1276
1277 let guar = if !fields.is_empty() &&
1278 self.span_to_snippet(close_paren).is_ok_and(|snippet| snippet == ")")
1283 {
1284 err.cancel();
1285 self.dcx()
1286 .create_err(errors::ParenthesesWithStructFields {
1287 span,
1288 r#type: path,
1289 braces_for_struct: errors::BracesForStructLiteral {
1290 first: open_paren,
1291 second: close_paren,
1292 },
1293 no_fields_for_fn: errors::NoFieldsForFnCall {
1294 fields: fields
1295 .into_iter()
1296 .map(|field| field.span.until(field.expr.span))
1297 .collect(),
1298 },
1299 })
1300 .emit()
1301 } else {
1302 err.emit()
1303 };
1304 Ok(self.mk_expr_err(span, guar))
1305 }
1306 Ok(_) => Err(err),
1307 Err(err2) => {
1308 err2.cancel();
1309 Err(err)
1310 }
1311 }
1312 }
1313 (_, seq, _) => seq,
1314 }
1315 }
1316
1317 fn parse_expr_index(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
1319 let prev_span = self.prev_token.span;
1320 let open_delim_span = self.token.span;
1321 self.bump(); let index = self.parse_expr()?;
1323 self.suggest_missing_semicolon_before_array(prev_span, open_delim_span)?;
1324 self.expect(exp!(CloseBracket))?;
1325 Ok(self.mk_expr(
1326 lo.to(self.prev_token.span),
1327 self.mk_index(base, index, open_delim_span.to(self.prev_token.span)),
1328 ))
1329 }
1330
1331 fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
1333 if self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await)) {
1334 return Ok(self.mk_await_expr(self_arg, lo));
1335 }
1336
1337 if self.eat_keyword(exp!(Match)) {
1339 let match_span = self.prev_token.span;
1340 self.psess.gated_spans.gate(sym::postfix_match, match_span);
1341 return self.parse_match_block(lo, match_span, self_arg, MatchKind::Postfix);
1342 }
1343
1344 let fn_span_lo = self.token.span;
1345 let mut seg = self.parse_path_segment(PathStyle::Expr, None)?;
1346 self.check_trailing_angle_brackets(&seg, &[exp!(OpenParen)]);
1347 self.check_turbofish_missing_angle_brackets(&mut seg);
1348
1349 if self.check(exp!(OpenParen)) {
1350 let args = self.parse_expr_paren_seq()?;
1352 let fn_span = fn_span_lo.to(self.prev_token.span);
1353 let span = lo.to(self.prev_token.span);
1354 Ok(self.mk_expr(
1355 span,
1356 ExprKind::MethodCall(Box::new(ast::MethodCall {
1357 seg,
1358 receiver: self_arg,
1359 args,
1360 span: fn_span,
1361 })),
1362 ))
1363 } else {
1364 let span = lo.to(self.prev_token.span);
1366 if let Some(args) = seg.args {
1367 self.dcx()
1369 .create_err(errors::FieldExpressionWithGeneric(args.span()))
1370 .stash(seg.ident.span, StashKey::GenericInFieldExpr);
1371 }
1372
1373 Ok(self.mk_expr(span, ExprKind::Field(self_arg, seg.ident)))
1374 }
1375 }
1376
1377 fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> {
1383 maybe_recover_from_interpolated_ty_qpath!(self, true);
1384
1385 if let token::Interpolated(nt) = &self.token.kind {
1386 match &**nt {
1387 token::NtExpr(e) | token::NtLiteral(e) => {
1388 let e = e.clone();
1389 self.bump();
1390 return Ok(e);
1391 }
1392 token::NtPath(path) => {
1393 let path = (**path).clone();
1394 self.bump();
1395 return Ok(self.mk_expr(self.prev_token.span, ExprKind::Path(None, path)));
1396 }
1397 token::NtBlock(block) => {
1398 let block = block.clone();
1399 self.bump();
1400 return Ok(self.mk_expr(self.prev_token.span, ExprKind::Block(block, None)));
1401 }
1402 _ => {}
1403 };
1404 }
1405
1406 let restrictions = self.restrictions;
1410 self.with_res(restrictions - Restrictions::ALLOW_LET, |this| {
1411 let lo = this.token.span;
1413 if let token::Literal(_) = this.token.kind {
1414 this.parse_expr_lit()
1418 } else if this.check(exp!(OpenParen)) {
1419 this.parse_expr_tuple_parens(restrictions)
1420 } else if this.check(exp!(OpenBrace)) {
1421 this.parse_expr_block(None, lo, BlockCheckMode::Default)
1422 } else if this.check(exp!(Or)) || this.check(exp!(OrOr)) {
1423 this.parse_expr_closure().map_err(|mut err| {
1424 if let Some(sp) = this.psess.ambiguous_block_expr_parse.borrow().get(&lo) {
1427 err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
1428 }
1429 err
1430 })
1431 } else if this.check(exp!(OpenBracket)) {
1432 this.parse_expr_array_or_repeat(exp!(CloseBracket))
1433 } else if this.is_builtin() {
1434 this.parse_expr_builtin()
1435 } else if this.check_path() {
1436 this.parse_expr_path_start()
1437 } else if this.check_keyword(exp!(Move))
1438 || this.check_keyword(exp!(Static))
1439 || this.check_const_closure()
1440 {
1441 this.parse_expr_closure()
1442 } else if this.eat_keyword(exp!(If)) {
1443 this.parse_expr_if()
1444 } else if this.check_keyword(exp!(For)) {
1445 if this.choose_generics_over_qpath(1) {
1446 this.parse_expr_closure()
1447 } else {
1448 assert!(this.eat_keyword(exp!(For)));
1449 this.parse_expr_for(None, lo)
1450 }
1451 } else if this.eat_keyword(exp!(While)) {
1452 this.parse_expr_while(None, lo)
1453 } else if let Some(label) = this.eat_label() {
1454 this.parse_expr_labeled(label, true)
1455 } else if this.eat_keyword(exp!(Loop)) {
1456 this.parse_expr_loop(None, lo).map_err(|mut err| {
1457 err.span_label(lo, "while parsing this `loop` expression");
1458 err
1459 })
1460 } else if this.eat_keyword(exp!(Match)) {
1461 this.parse_expr_match().map_err(|mut err| {
1462 err.span_label(lo, "while parsing this `match` expression");
1463 err
1464 })
1465 } else if this.eat_keyword(exp!(Unsafe)) {
1466 this.parse_expr_block(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
1467 |mut err| {
1468 err.span_label(lo, "while parsing this `unsafe` expression");
1469 err
1470 },
1471 )
1472 } else if this.check_inline_const(0) {
1473 this.parse_const_block(lo, false)
1474 } else if this.may_recover() && this.is_do_catch_block() {
1475 this.recover_do_catch()
1476 } else if this.is_try_block() {
1477 this.expect_keyword(exp!(Try))?;
1478 this.parse_try_block(lo)
1479 } else if this.eat_keyword(exp!(Return)) {
1480 this.parse_expr_return()
1481 } else if this.eat_keyword(exp!(Continue)) {
1482 this.parse_expr_continue(lo)
1483 } else if this.eat_keyword(exp!(Break)) {
1484 this.parse_expr_break()
1485 } else if this.eat_keyword(exp!(Yield)) {
1486 this.parse_expr_yield()
1487 } else if this.is_do_yeet() {
1488 this.parse_expr_yeet()
1489 } else if this.eat_keyword(exp!(Become)) {
1490 this.parse_expr_become()
1491 } else if this.check_keyword(exp!(Let)) {
1492 this.parse_expr_let(restrictions)
1493 } else if this.eat_keyword(exp!(Underscore)) {
1494 Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore))
1495 } else if this.token.uninterpolated_span().at_least_rust_2018() {
1496 if this.token.uninterpolated_span().at_least_rust_2024()
1498 && (this.is_gen_block(kw::Gen, 0)
1501 || (this.check_keyword(exp!(Async)) && this.is_gen_block(kw::Gen, 1)))
1502 {
1503 this.parse_gen_block()
1505 } else if this.check_keyword(exp!(Async)) {
1506 if this.is_gen_block(kw::Async, 0) {
1508 this.parse_gen_block()
1510 } else {
1511 this.parse_expr_closure()
1512 }
1513 } else if this.eat_keyword_noexpect(kw::Await) {
1514 this.recover_incorrect_await_syntax(lo)
1515 } else {
1516 this.parse_expr_lit()
1517 }
1518 } else {
1519 this.parse_expr_lit()
1520 }
1521 })
1522 }
1523
1524 fn parse_expr_lit(&mut self) -> PResult<'a, P<Expr>> {
1525 let lo = self.token.span;
1526 match self.parse_opt_token_lit() {
1527 Some((token_lit, _)) => {
1528 let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(token_lit));
1529 self.maybe_recover_from_bad_qpath(expr)
1530 }
1531 None => self.try_macro_suggestion(),
1532 }
1533 }
1534
1535 fn parse_expr_tuple_parens(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> {
1536 let lo = self.token.span;
1537 self.expect(exp!(OpenParen))?;
1538 let (es, trailing_comma) = match self.parse_seq_to_end(
1539 exp!(CloseParen),
1540 SeqSep::trailing_allowed(exp!(Comma)),
1541 |p| p.parse_expr_catch_underscore(restrictions.intersection(Restrictions::ALLOW_LET)),
1542 ) {
1543 Ok(x) => x,
1544 Err(err) => {
1545 return Ok(self.recover_seq_parse_error(
1546 exp!(OpenParen),
1547 exp!(CloseParen),
1548 lo,
1549 err,
1550 ));
1551 }
1552 };
1553 let kind = if es.len() == 1 && matches!(trailing_comma, Trailing::No) {
1554 ExprKind::Paren(es.into_iter().next().unwrap())
1556 } else {
1557 ExprKind::Tup(es)
1559 };
1560 let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
1561 self.maybe_recover_from_bad_qpath(expr)
1562 }
1563
1564 fn parse_expr_array_or_repeat(&mut self, close: ExpTokenPair<'_>) -> PResult<'a, P<Expr>> {
1565 let lo = self.token.span;
1566 self.bump(); let kind = if self.eat(close) {
1569 ExprKind::Array(ThinVec::new())
1571 } else {
1572 let first_expr = self.parse_expr()?;
1574 if self.eat(exp!(Semi)) {
1575 let count = self.parse_expr_anon_const()?;
1577 self.expect(close)?;
1578 ExprKind::Repeat(first_expr, count)
1579 } else if self.eat(exp!(Comma)) {
1580 let sep = SeqSep::trailing_allowed(exp!(Comma));
1582 let (mut exprs, _) = self.parse_seq_to_end(close, sep, |p| p.parse_expr())?;
1583 exprs.insert(0, first_expr);
1584 ExprKind::Array(exprs)
1585 } else {
1586 self.expect(close)?;
1588 ExprKind::Array(thin_vec![first_expr])
1589 }
1590 };
1591 let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
1592 self.maybe_recover_from_bad_qpath(expr)
1593 }
1594
1595 fn parse_expr_path_start(&mut self) -> PResult<'a, P<Expr>> {
1596 let maybe_eq_tok = self.prev_token.clone();
1597 let (qself, path) = if self.eat_lt() {
1598 let lt_span = self.prev_token.span;
1599 let (qself, path) = self.parse_qpath(PathStyle::Expr).map_err(|mut err| {
1600 if maybe_eq_tok == TokenKind::Eq && maybe_eq_tok.span.hi() == lt_span.lo() {
1604 let eq_lt = maybe_eq_tok.span.to(lt_span);
1605 err.span_suggestion(eq_lt, "did you mean", "<=", Applicability::Unspecified);
1606 }
1607 err
1608 })?;
1609 (Some(qself), path)
1610 } else {
1611 (None, self.parse_path(PathStyle::Expr)?)
1612 };
1613
1614 let (span, kind) = if self.eat(exp!(Not)) {
1616 if qself.is_some() {
1618 self.dcx().emit_err(errors::MacroInvocationWithQualifiedPath(path.span));
1619 }
1620 let lo = path.span;
1621 let mac = P(MacCall { path, args: self.parse_delim_args()? });
1622 (lo.to(self.prev_token.span), ExprKind::MacCall(mac))
1623 } else if self.check(exp!(OpenBrace))
1624 && let Some(expr) = self.maybe_parse_struct_expr(&qself, &path)
1625 {
1626 if qself.is_some() {
1627 self.psess.gated_spans.gate(sym::more_qualified_paths, path.span);
1628 }
1629 return expr;
1630 } else {
1631 (path.span, ExprKind::Path(qself, path))
1632 };
1633
1634 let expr = self.mk_expr(span, kind);
1635 self.maybe_recover_from_bad_qpath(expr)
1636 }
1637
1638 pub(super) fn parse_expr_labeled(
1640 &mut self,
1641 label_: Label,
1642 mut consume_colon: bool,
1643 ) -> PResult<'a, P<Expr>> {
1644 let lo = label_.ident.span;
1645 let label = Some(label_);
1646 let ate_colon = self.eat(exp!(Colon));
1647 let tok_sp = self.token.span;
1648 let expr = if self.eat_keyword(exp!(While)) {
1649 self.parse_expr_while(label, lo)
1650 } else if self.eat_keyword(exp!(For)) {
1651 self.parse_expr_for(label, lo)
1652 } else if self.eat_keyword(exp!(Loop)) {
1653 self.parse_expr_loop(label, lo)
1654 } else if self.check_noexpect(&token::OpenDelim(Delimiter::Brace))
1655 || self.token.is_whole_block()
1656 {
1657 self.parse_expr_block(label, lo, BlockCheckMode::Default)
1658 } else if !ate_colon
1659 && self.may_recover()
1660 && (matches!(self.token.kind, token::CloseDelim(_) | token::Comma)
1661 || self.token.is_punct())
1662 && could_be_unclosed_char_literal(label_.ident)
1663 {
1664 let (lit, _) =
1665 self.recover_unclosed_char(label_.ident, Parser::mk_token_lit_char, |self_| {
1666 self_.dcx().create_err(errors::UnexpectedTokenAfterLabel {
1667 span: self_.token.span,
1668 remove_label: None,
1669 enclose_in_block: None,
1670 })
1671 });
1672 consume_colon = false;
1673 Ok(self.mk_expr(lo, ExprKind::Lit(lit)))
1674 } else if !ate_colon
1675 && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
1676 {
1677 let guar = self.dcx().emit_err(errors::UnexpectedTokenAfterLabel {
1679 span: self.token.span,
1680 remove_label: None,
1681 enclose_in_block: None,
1682 });
1683 consume_colon = false;
1684 Ok(self.mk_expr_err(lo, guar))
1685 } else {
1686 let mut err = errors::UnexpectedTokenAfterLabel {
1687 span: self.token.span,
1688 remove_label: None,
1689 enclose_in_block: None,
1690 };
1691
1692 let expr = self.parse_expr().map(|expr| {
1694 let span = expr.span;
1695
1696 let found_labeled_breaks = {
1697 struct FindLabeledBreaksVisitor;
1698
1699 impl<'ast> Visitor<'ast> for FindLabeledBreaksVisitor {
1700 type Result = ControlFlow<()>;
1701 fn visit_expr(&mut self, ex: &'ast Expr) -> ControlFlow<()> {
1702 if let ExprKind::Break(Some(_label), _) = ex.kind {
1703 ControlFlow::Break(())
1704 } else {
1705 walk_expr(self, ex)
1706 }
1707 }
1708 }
1709
1710 FindLabeledBreaksVisitor.visit_expr(&expr).is_break()
1711 };
1712
1713 if !found_labeled_breaks {
1718 err.remove_label = Some(lo.until(span));
1719
1720 return expr;
1721 }
1722
1723 err.enclose_in_block = Some(errors::UnexpectedTokenAfterLabelSugg {
1724 left: span.shrink_to_lo(),
1725 right: span.shrink_to_hi(),
1726 });
1727
1728 let stmt = self.mk_stmt(span, StmtKind::Expr(expr));
1730 let blk = self.mk_block(thin_vec![stmt], BlockCheckMode::Default, span);
1731 self.mk_expr(span, ExprKind::Block(blk, label))
1732 });
1733
1734 self.dcx().emit_err(err);
1735 expr
1736 }?;
1737
1738 if !ate_colon && consume_colon {
1739 self.dcx().emit_err(errors::RequireColonAfterLabeledExpression {
1740 span: expr.span,
1741 label: lo,
1742 label_end: lo.between(tok_sp),
1743 });
1744 }
1745
1746 Ok(expr)
1747 }
1748
1749 pub(super) fn recover_unclosed_char<L>(
1751 &self,
1752 ident: Ident,
1753 mk_lit_char: impl FnOnce(Symbol, Span) -> L,
1754 err: impl FnOnce(&Self) -> Diag<'a>,
1755 ) -> L {
1756 assert!(could_be_unclosed_char_literal(ident));
1757 self.dcx()
1758 .try_steal_modify_and_emit_err(ident.span, StashKey::LifetimeIsChar, |err| {
1759 err.span_suggestion_verbose(
1760 ident.span.shrink_to_hi(),
1761 "add `'` to close the char literal",
1762 "'",
1763 Applicability::MaybeIncorrect,
1764 );
1765 })
1766 .unwrap_or_else(|| {
1767 err(self)
1768 .with_span_suggestion_verbose(
1769 ident.span.shrink_to_hi(),
1770 "add `'` to close the char literal",
1771 "'",
1772 Applicability::MaybeIncorrect,
1773 )
1774 .emit()
1775 });
1776 let name = ident.without_first_quote().name;
1777 mk_lit_char(name, ident.span)
1778 }
1779
1780 fn recover_do_catch(&mut self) -> PResult<'a, P<Expr>> {
1782 let lo = self.token.span;
1783
1784 self.bump(); self.bump(); let span = lo.to(self.prev_token.span);
1788 self.dcx().emit_err(errors::DoCatchSyntaxRemoved { span });
1789
1790 self.parse_try_block(lo)
1791 }
1792
1793 fn parse_expr_opt(&mut self) -> PResult<'a, Option<P<Expr>>> {
1795 Ok(if self.token.can_begin_expr() { Some(self.parse_expr()?) } else { None })
1796 }
1797
1798 fn parse_expr_return(&mut self) -> PResult<'a, P<Expr>> {
1800 let lo = self.prev_token.span;
1801 let kind = ExprKind::Ret(self.parse_expr_opt()?);
1802 let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
1803 self.maybe_recover_from_bad_qpath(expr)
1804 }
1805
1806 fn parse_expr_yeet(&mut self) -> PResult<'a, P<Expr>> {
1808 let lo = self.token.span;
1809
1810 self.bump(); self.bump(); let kind = ExprKind::Yeet(self.parse_expr_opt()?);
1814
1815 let span = lo.to(self.prev_token.span);
1816 self.psess.gated_spans.gate(sym::yeet_expr, span);
1817 let expr = self.mk_expr(span, kind);
1818 self.maybe_recover_from_bad_qpath(expr)
1819 }
1820
1821 fn parse_expr_become(&mut self) -> PResult<'a, P<Expr>> {
1823 let lo = self.prev_token.span;
1824 let kind = ExprKind::Become(self.parse_expr()?);
1825 let span = lo.to(self.prev_token.span);
1826 self.psess.gated_spans.gate(sym::explicit_tail_calls, span);
1827 let expr = self.mk_expr(span, kind);
1828 self.maybe_recover_from_bad_qpath(expr)
1829 }
1830
1831 fn parse_expr_break(&mut self) -> PResult<'a, P<Expr>> {
1840 let lo = self.prev_token.span;
1841 let mut label = self.eat_label();
1842 let kind = if self.token == token::Colon
1843 && let Some(label) = label.take()
1844 {
1845 let lexpr = self.parse_expr_labeled(label, true)?;
1848 self.dcx().emit_err(errors::LabeledLoopInBreak {
1849 span: lexpr.span,
1850 sub: errors::WrapInParentheses::Expression {
1851 left: lexpr.span.shrink_to_lo(),
1852 right: lexpr.span.shrink_to_hi(),
1853 },
1854 });
1855 Some(lexpr)
1856 } else if self.token != token::OpenDelim(Delimiter::Brace)
1857 || !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
1858 {
1859 let mut expr = self.parse_expr_opt()?;
1860 if let Some(expr) = &mut expr {
1861 if label.is_some()
1862 && matches!(
1863 expr.kind,
1864 ExprKind::While(_, _, None)
1865 | ExprKind::ForLoop { label: None, .. }
1866 | ExprKind::Loop(_, None, _)
1867 | ExprKind::Block(_, None)
1868 )
1869 {
1870 self.psess.buffer_lint(
1871 BREAK_WITH_LABEL_AND_LOOP,
1872 lo.to(expr.span),
1873 ast::CRATE_NODE_ID,
1874 BuiltinLintDiag::BreakWithLabelAndLoop(expr.span),
1875 );
1876 }
1877
1878 if self.may_recover()
1880 && let ExprKind::Path(None, p) = &expr.kind
1881 && let [segment] = &*p.segments
1882 && let &ast::PathSegment { ident, args: None, .. } = segment
1883 && let Some(next) = self.parse_expr_opt()?
1884 {
1885 label = Some(self.recover_ident_into_label(ident));
1886 *expr = next;
1887 }
1888 }
1889
1890 expr
1891 } else {
1892 None
1893 };
1894 let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Break(label, kind));
1895 self.maybe_recover_from_bad_qpath(expr)
1896 }
1897
1898 fn parse_expr_continue(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
1900 let mut label = self.eat_label();
1901
1902 if self.may_recover()
1904 && label.is_none()
1905 && let Some((ident, _)) = self.token.ident()
1906 {
1907 self.bump();
1908 label = Some(self.recover_ident_into_label(ident));
1909 }
1910
1911 let kind = ExprKind::Continue(label);
1912 Ok(self.mk_expr(lo.to(self.prev_token.span), kind))
1913 }
1914
1915 fn parse_expr_yield(&mut self) -> PResult<'a, P<Expr>> {
1917 let lo = self.prev_token.span;
1918 let kind = ExprKind::Yield(self.parse_expr_opt()?);
1919 let span = lo.to(self.prev_token.span);
1920 self.psess.gated_spans.gate(sym::yield_expr, span);
1921 let expr = self.mk_expr(span, kind);
1922 self.maybe_recover_from_bad_qpath(expr)
1923 }
1924
1925 fn parse_expr_builtin(&mut self) -> PResult<'a, P<Expr>> {
1927 self.parse_builtin(|this, lo, ident| {
1928 Ok(match ident.name {
1929 sym::offset_of => Some(this.parse_expr_offset_of(lo)?),
1930 sym::type_ascribe => Some(this.parse_expr_type_ascribe(lo)?),
1931 sym::wrap_binder => {
1932 Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Wrap)?)
1933 }
1934 sym::unwrap_binder => {
1935 Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Unwrap)?)
1936 }
1937 _ => None,
1938 })
1939 })
1940 }
1941
1942 pub(crate) fn parse_builtin<T>(
1943 &mut self,
1944 parse: impl FnOnce(&mut Parser<'a>, Span, Ident) -> PResult<'a, Option<T>>,
1945 ) -> PResult<'a, T> {
1946 let lo = self.token.span;
1947
1948 self.bump(); self.bump(); let Some((ident, IdentIsRaw::No)) = self.token.ident() else {
1952 let err = self.dcx().create_err(errors::ExpectedBuiltinIdent { span: self.token.span });
1953 return Err(err);
1954 };
1955 self.psess.gated_spans.gate(sym::builtin_syntax, ident.span);
1956 self.bump();
1957
1958 self.expect(exp!(OpenParen))?;
1959 let ret = if let Some(res) = parse(self, lo, ident)? {
1960 Ok(res)
1961 } else {
1962 let err = self.dcx().create_err(errors::UnknownBuiltinConstruct {
1963 span: lo.to(ident.span),
1964 name: ident,
1965 });
1966 return Err(err);
1967 };
1968 self.expect(exp!(CloseParen))?;
1969
1970 ret
1971 }
1972
1973 pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
1975 let container = self.parse_ty()?;
1976 self.expect(exp!(Comma))?;
1977
1978 let fields = self.parse_floating_field_access()?;
1979 let trailing_comma = self.eat_noexpect(&TokenKind::Comma);
1980
1981 if let Err(mut e) = self.expect_one_of(&[], &[exp!(CloseParen)]) {
1982 if trailing_comma {
1983 e.note("unexpected third argument to offset_of");
1984 } else {
1985 e.note("offset_of expects dot-separated field and variant names");
1986 }
1987 e.emit();
1988 }
1989
1990 if self.may_recover() {
1992 while !matches!(self.token.kind, token::CloseDelim(..) | token::Eof) {
1993 self.bump();
1994 }
1995 }
1996
1997 let span = lo.to(self.token.span);
1998 Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields)))
1999 }
2000
2001 pub(crate) fn parse_expr_type_ascribe(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
2003 let expr = self.parse_expr()?;
2004 self.expect(exp!(Comma))?;
2005 let ty = self.parse_ty()?;
2006 let span = lo.to(self.token.span);
2007 Ok(self.mk_expr(span, ExprKind::Type(expr, ty)))
2008 }
2009
2010 pub(crate) fn parse_expr_unsafe_binder_cast(
2011 &mut self,
2012 lo: Span,
2013 kind: UnsafeBinderCastKind,
2014 ) -> PResult<'a, P<Expr>> {
2015 let expr = self.parse_expr()?;
2016 let ty = if self.eat(exp!(Comma)) { Some(self.parse_ty()?) } else { None };
2017 let span = lo.to(self.token.span);
2018 Ok(self.mk_expr(span, ExprKind::UnsafeBinderCast(kind, expr, ty)))
2019 }
2020
2021 pub fn parse_str_lit(&mut self) -> Result<ast::StrLit, Option<MetaItemLit>> {
2025 match self.parse_opt_meta_item_lit() {
2026 Some(lit) => match lit.kind {
2027 ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit {
2028 style,
2029 symbol: lit.symbol,
2030 suffix: lit.suffix,
2031 span: lit.span,
2032 symbol_unescaped,
2033 }),
2034 _ => Err(Some(lit)),
2035 },
2036 None => Err(None),
2037 }
2038 }
2039
2040 pub(crate) fn mk_token_lit_char(name: Symbol, span: Span) -> (token::Lit, Span) {
2041 (token::Lit { symbol: name, suffix: None, kind: token::Char }, span)
2042 }
2043
2044 fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit {
2045 ast::MetaItemLit {
2046 symbol: name,
2047 suffix: None,
2048 kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')),
2049 span,
2050 }
2051 }
2052
2053 fn handle_missing_lit<L>(
2054 &mut self,
2055 mk_lit_char: impl FnOnce(Symbol, Span) -> L,
2056 ) -> PResult<'a, L> {
2057 let token = self.token.clone();
2058 let err = |self_: &Self| {
2059 let msg = format!("unexpected token: {}", super::token_descr(&token));
2060 self_.dcx().struct_span_err(token.span, msg)
2061 };
2062 if let Some((ident, IdentIsRaw::No)) = self.token.lifetime()
2065 && could_be_unclosed_char_literal(ident)
2066 {
2067 let lt = self.expect_lifetime();
2068 Ok(self.recover_unclosed_char(lt.ident, mk_lit_char, err))
2069 } else {
2070 Err(err(self))
2071 }
2072 }
2073
2074 pub(super) fn parse_token_lit(&mut self) -> PResult<'a, (token::Lit, Span)> {
2075 self.parse_opt_token_lit()
2076 .ok_or(())
2077 .or_else(|()| self.handle_missing_lit(Parser::mk_token_lit_char))
2078 }
2079
2080 pub(super) fn parse_meta_item_lit(&mut self) -> PResult<'a, MetaItemLit> {
2081 self.parse_opt_meta_item_lit()
2082 .ok_or(())
2083 .or_else(|()| self.handle_missing_lit(Parser::mk_meta_item_lit_char))
2084 }
2085
2086 fn recover_after_dot(&mut self) -> Option<Token> {
2087 let mut recovered = None;
2088 if self.token == token::Dot {
2089 recovered = self.look_ahead(1, |next_token| {
2092 if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) =
2093 next_token.kind
2094 {
2095 if suffix.is_none_or(|s| s == sym::f32 || s == sym::f64)
2102 && symbol.as_str().chars().all(|c| c.is_numeric() || c == '_')
2103 && self.token.span.hi() == next_token.span.lo()
2104 {
2105 let s = String::from("0.") + symbol.as_str();
2106 let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix);
2107 return Some(Token::new(kind, self.token.span.to(next_token.span)));
2108 }
2109 }
2110 None
2111 });
2112 if let Some(token) = &recovered {
2113 self.bump();
2114 self.dcx().emit_err(errors::FloatLiteralRequiresIntegerPart {
2115 span: token.span,
2116 suggestion: token.span.shrink_to_lo(),
2117 });
2118 }
2119 }
2120
2121 recovered
2122 }
2123
2124 pub(super) fn parse_opt_token_lit(&mut self) -> Option<(token::Lit, Span)> {
2127 let recovered = self.recover_after_dot();
2128 let token = recovered.as_ref().unwrap_or(&self.token);
2129 let span = token.span;
2130
2131 token::Lit::from_token(token).map(|token_lit| {
2132 self.bump();
2133 (token_lit, span)
2134 })
2135 }
2136
2137 pub(super) fn parse_opt_meta_item_lit(&mut self) -> Option<MetaItemLit> {
2140 let recovered = self.recover_after_dot();
2141 let token = recovered.as_ref().unwrap_or(&self.token);
2142 match token::Lit::from_token(token) {
2143 Some(lit) => {
2144 match MetaItemLit::from_token_lit(lit, token.span) {
2145 Ok(lit) => {
2146 self.bump();
2147 Some(lit)
2148 }
2149 Err(err) => {
2150 let span = token.uninterpolated_span();
2151 self.bump();
2152 let guar = report_lit_error(self.psess, err, lit, span);
2153 let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None);
2156 let symbol = Symbol::intern(&suffixless_lit.to_string());
2157 let lit = token::Lit::new(token::Err(guar), symbol, lit.suffix);
2158 Some(
2159 MetaItemLit::from_token_lit(lit, span)
2160 .unwrap_or_else(|_| unreachable!()),
2161 )
2162 }
2163 }
2164 }
2165 None => None,
2166 }
2167 }
2168
2169 pub(super) fn expect_no_tuple_index_suffix(&self, span: Span, suffix: Symbol) {
2170 if [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suffix) {
2171 self.dcx().emit_warn(errors::InvalidLiteralSuffixOnTupleIndex {
2174 span,
2175 suffix,
2176 exception: true,
2177 });
2178 } else {
2179 self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex {
2180 span,
2181 suffix,
2182 exception: false,
2183 });
2184 }
2185 }
2186
2187 pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
2190 if let token::Interpolated(nt) = &self.token.kind {
2191 match &**nt {
2192 token::NtExpr(e) | token::NtLiteral(e) => {
2203 let e = e.clone();
2204 self.bump();
2205 return Ok(e);
2206 }
2207 _ => {}
2208 };
2209 }
2210
2211 let lo = self.token.span;
2212 let minus_present = self.eat(exp!(Minus));
2213 let (token_lit, span) = self.parse_token_lit()?;
2214 let expr = self.mk_expr(span, ExprKind::Lit(token_lit));
2215
2216 if minus_present {
2217 Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_unary(UnOp::Neg, expr)))
2218 } else {
2219 Ok(expr)
2220 }
2221 }
2222
2223 fn is_array_like_block(&mut self) -> bool {
2224 self.look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_)))
2225 && self.look_ahead(2, |t| t == &token::Comma)
2226 && self.look_ahead(3, |t| t.can_begin_expr())
2227 }
2228
2229 fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<P<Expr>> {
2233 let mut snapshot = self.create_snapshot_for_diagnostic();
2234 match snapshot.parse_expr_array_or_repeat(exp!(CloseBrace)) {
2235 Ok(arr) => {
2236 let guar = self.dcx().emit_err(errors::ArrayBracketsInsteadOfSpaces {
2237 span: arr.span,
2238 sub: errors::ArrayBracketsInsteadOfSpacesSugg {
2239 left: lo,
2240 right: snapshot.prev_token.span,
2241 },
2242 });
2243
2244 self.restore_snapshot(snapshot);
2245 Some(self.mk_expr_err(arr.span, guar))
2246 }
2247 Err(e) => {
2248 e.cancel();
2249 None
2250 }
2251 }
2252 }
2253
2254 fn suggest_missing_semicolon_before_array(
2255 &self,
2256 prev_span: Span,
2257 open_delim_span: Span,
2258 ) -> PResult<'a, ()> {
2259 if !self.may_recover() {
2260 return Ok(());
2261 }
2262
2263 if self.token == token::Comma {
2264 if !self.psess.source_map().is_multiline(prev_span.until(self.token.span)) {
2265 return Ok(());
2266 }
2267 let mut snapshot = self.create_snapshot_for_diagnostic();
2268 snapshot.bump();
2269 match snapshot.parse_seq_to_before_end(
2270 exp!(CloseBracket),
2271 SeqSep::trailing_allowed(exp!(Comma)),
2272 |p| p.parse_expr(),
2273 ) {
2274 Ok(_)
2275 if snapshot
2281 .span_to_snippet(snapshot.token.span)
2282 .is_ok_and(|snippet| snippet == "]") =>
2283 {
2284 return Err(self.dcx().create_err(errors::MissingSemicolonBeforeArray {
2285 open_delim: open_delim_span,
2286 semicolon: prev_span.shrink_to_hi(),
2287 }));
2288 }
2289 Ok(_) => (),
2290 Err(err) => err.cancel(),
2291 }
2292 }
2293 Ok(())
2294 }
2295
2296 pub(super) fn parse_expr_block(
2298 &mut self,
2299 opt_label: Option<Label>,
2300 lo: Span,
2301 blk_mode: BlockCheckMode,
2302 ) -> PResult<'a, P<Expr>> {
2303 if self.may_recover() && self.is_array_like_block() {
2304 if let Some(arr) = self.maybe_suggest_brackets_instead_of_braces(lo) {
2305 return Ok(arr);
2306 }
2307 }
2308
2309 if self.token.is_whole_block() {
2310 self.dcx().emit_err(errors::InvalidBlockMacroSegment {
2311 span: self.token.span,
2312 context: lo.to(self.token.span),
2313 wrap: errors::WrapInExplicitBlock {
2314 lo: self.token.span.shrink_to_lo(),
2315 hi: self.token.span.shrink_to_hi(),
2316 },
2317 });
2318 }
2319
2320 let (attrs, blk) = self.parse_block_common(lo, blk_mode, true)?;
2321 Ok(self.mk_expr_with_attrs(blk.span, ExprKind::Block(blk, opt_label), attrs))
2322 }
2323
2324 fn parse_simple_block(&mut self) -> PResult<'a, P<Expr>> {
2326 let blk = self.parse_block()?;
2327 Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None)))
2328 }
2329
2330 fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> {
2332 let lo = self.token.span;
2333
2334 let before = self.prev_token.clone();
2335 let binder = if self.check_keyword(exp!(For)) {
2336 let lo = self.token.span;
2337 let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?;
2338 let span = lo.to(self.prev_token.span);
2339
2340 self.psess.gated_spans.gate(sym::closure_lifetime_binder, span);
2341
2342 ClosureBinder::For { span, generic_params: lifetime_defs }
2343 } else {
2344 ClosureBinder::NotPresent
2345 };
2346
2347 let constness = self.parse_closure_constness();
2348
2349 let movability =
2350 if self.eat_keyword(exp!(Static)) { Movability::Static } else { Movability::Movable };
2351
2352 let coroutine_kind = if self.token.uninterpolated_span().at_least_rust_2018() {
2353 self.parse_coroutine_kind(Case::Sensitive)
2354 } else {
2355 None
2356 };
2357
2358 let capture_clause = self.parse_capture_clause()?;
2359 let (fn_decl, fn_arg_span) = self.parse_fn_block_decl()?;
2360 let decl_hi = self.prev_token.span;
2361 let mut body = match fn_decl.output {
2362 FnRetTy::Default(_) => {
2363 let restrictions =
2364 self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
2365 let prev = self.prev_token.clone();
2366 let token = self.token.clone();
2367 let attrs = self.parse_outer_attributes()?;
2368 match self.parse_expr_res(restrictions, attrs) {
2369 Ok((expr, _)) => expr,
2370 Err(err) => self.recover_closure_body(err, before, prev, token, lo, decl_hi)?,
2371 }
2372 }
2373 _ => {
2374 let body_lo = self.token.span;
2376 self.parse_expr_block(None, body_lo, BlockCheckMode::Default)?
2377 }
2378 };
2379
2380 match coroutine_kind {
2381 Some(CoroutineKind::Async { .. }) => {}
2382 Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => {
2383 self.psess.gated_spans.gate(sym::gen_blocks, span);
2386 }
2387 None => {}
2388 }
2389
2390 if self.token == TokenKind::Semi
2391 && let Some(last) = self.token_cursor.stack.last()
2392 && let Some(TokenTree::Delimited(_, _, Delimiter::Parenthesis, _)) = last.curr()
2393 && self.may_recover()
2394 {
2395 body = self.mk_expr_err(
2399 body.span,
2400 self.dcx().span_delayed_bug(body.span, "recovered a closure body as a block"),
2401 );
2402 }
2403
2404 let body_span = body.span;
2405
2406 let closure = self.mk_expr(
2407 lo.to(body.span),
2408 ExprKind::Closure(Box::new(ast::Closure {
2409 binder,
2410 capture_clause,
2411 constness,
2412 coroutine_kind,
2413 movability,
2414 fn_decl,
2415 body,
2416 fn_decl_span: lo.to(decl_hi),
2417 fn_arg_span,
2418 })),
2419 );
2420
2421 let spans =
2423 ClosureSpans { whole_closure: closure.span, closing_pipe: decl_hi, body: body_span };
2424 self.current_closure = Some(spans);
2425
2426 Ok(closure)
2427 }
2428
2429 fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> {
2431 if self.eat_keyword(exp!(Move)) {
2432 let move_kw_span = self.prev_token.span;
2433 if self.check_keyword(exp!(Async)) {
2435 let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
2436 Err(self
2437 .dcx()
2438 .create_err(errors::AsyncMoveOrderIncorrect { span: move_async_span }))
2439 } else {
2440 Ok(CaptureBy::Value { move_kw: move_kw_span })
2441 }
2442 } else {
2443 Ok(CaptureBy::Ref)
2444 }
2445 }
2446
2447 fn parse_fn_block_decl(&mut self) -> PResult<'a, (P<FnDecl>, Span)> {
2449 let arg_start = self.token.span.lo();
2450
2451 let inputs = if self.eat(exp!(OrOr)) {
2452 ThinVec::new()
2453 } else {
2454 self.expect(exp!(Or))?;
2455 let args = self
2456 .parse_seq_to_before_tokens(
2457 &[exp!(Or)],
2458 &[&token::OrOr],
2459 SeqSep::trailing_allowed(exp!(Comma)),
2460 |p| p.parse_fn_block_param(),
2461 )?
2462 .0;
2463 self.expect_or()?;
2464 args
2465 };
2466 let arg_span = self.prev_token.span.with_lo(arg_start);
2467 let output =
2468 self.parse_ret_ty(AllowPlus::Yes, RecoverQPath::Yes, RecoverReturnSign::Yes)?;
2469
2470 Ok((P(FnDecl { inputs, output }), arg_span))
2471 }
2472
2473 fn parse_fn_block_param(&mut self) -> PResult<'a, Param> {
2475 let lo = self.token.span;
2476 let attrs = self.parse_outer_attributes()?;
2477 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
2478 let pat = this.parse_pat_no_top_alt(Some(Expected::ParameterName), None)?;
2479 let ty = if this.eat(exp!(Colon)) {
2480 this.parse_ty()?
2481 } else {
2482 this.mk_ty(pat.span, TyKind::Infer)
2483 };
2484
2485 Ok((
2486 Param {
2487 attrs,
2488 ty,
2489 pat,
2490 span: lo.to(this.prev_token.span),
2491 id: DUMMY_NODE_ID,
2492 is_placeholder: false,
2493 },
2494 Trailing::from(this.token == token::Comma),
2495 UsePreAttrPos::No,
2496 ))
2497 })
2498 }
2499
2500 fn parse_expr_if(&mut self) -> PResult<'a, P<Expr>> {
2502 let lo = self.prev_token.span;
2503 let cond = self.parse_expr_cond()?;
2504 self.parse_if_after_cond(lo, cond)
2505 }
2506
2507 fn parse_if_after_cond(&mut self, lo: Span, mut cond: P<Expr>) -> PResult<'a, P<Expr>> {
2508 let cond_span = cond.span;
2509 let mut recover_block_from_condition = |this: &mut Self| {
2513 let block = match &mut cond.kind {
2514 ExprKind::Binary(Spanned { span: binop_span, .. }, _, right)
2515 if let ExprKind::Block(_, None) = right.kind =>
2516 {
2517 let guar = this.dcx().emit_err(errors::IfExpressionMissingThenBlock {
2518 if_span: lo,
2519 missing_then_block_sub:
2520 errors::IfExpressionMissingThenBlockSub::UnfinishedCondition(
2521 cond_span.shrink_to_lo().to(*binop_span),
2522 ),
2523 let_else_sub: None,
2524 });
2525 std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi(), guar))
2526 }
2527 ExprKind::Block(_, None) => {
2528 let guar = this.dcx().emit_err(errors::IfExpressionMissingCondition {
2529 if_span: lo.with_neighbor(cond.span).shrink_to_hi(),
2530 block_span: self.psess.source_map().start_point(cond_span),
2531 });
2532 std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi(), guar))
2533 }
2534 _ => {
2535 return None;
2536 }
2537 };
2538 if let ExprKind::Block(block, _) = &block.kind {
2539 Some(block.clone())
2540 } else {
2541 unreachable!()
2542 }
2543 };
2544 let thn = if self.token.is_keyword(kw::Else) {
2546 if let Some(block) = recover_block_from_condition(self) {
2547 block
2548 } else {
2549 let let_else_sub = matches!(cond.kind, ExprKind::Let(..))
2550 .then(|| errors::IfExpressionLetSomeSub { if_span: lo.until(cond_span) });
2551
2552 let guar = self.dcx().emit_err(errors::IfExpressionMissingThenBlock {
2553 if_span: lo,
2554 missing_then_block_sub: errors::IfExpressionMissingThenBlockSub::AddThenBlock(
2555 cond_span.shrink_to_hi(),
2556 ),
2557 let_else_sub,
2558 });
2559 self.mk_block_err(cond_span.shrink_to_hi(), guar)
2560 }
2561 } else {
2562 let attrs = self.parse_outer_attributes()?; let maybe_fatarrow = self.token.clone();
2564 let block = if self.check(exp!(OpenBrace)) {
2565 self.parse_block()?
2566 } else if let Some(block) = recover_block_from_condition(self) {
2567 block
2568 } else {
2569 self.error_on_extra_if(&cond)?;
2570 self.parse_block().map_err(|mut err| {
2572 if self.prev_token == token::Semi
2573 && self.token == token::AndAnd
2574 && let maybe_let = self.look_ahead(1, |t| t.clone())
2575 && maybe_let.is_keyword(kw::Let)
2576 {
2577 err.span_suggestion(
2578 self.prev_token.span,
2579 "consider removing this semicolon to parse the `let` as part of the same chain",
2580 "",
2581 Applicability::MachineApplicable,
2582 ).span_note(
2583 self.token.span.to(maybe_let.span),
2584 "you likely meant to continue parsing the let-chain starting here",
2585 );
2586 } else {
2587 if maybe_fatarrow == token::FatArrow {
2589 err.span_suggestion(
2590 maybe_fatarrow.span,
2591 "you might have meant to write a \"greater than or equal to\" comparison",
2592 ">=",
2593 Applicability::MaybeIncorrect,
2594 );
2595 }
2596 err.span_note(
2597 cond_span,
2598 "the `if` expression is missing a block after this condition",
2599 );
2600 }
2601 err
2602 })?
2603 };
2604 self.error_on_if_block_attrs(lo, false, block.span, attrs);
2605 block
2606 };
2607 let els = if self.eat_keyword(exp!(Else)) { Some(self.parse_expr_else()?) } else { None };
2608 Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els)))
2609 }
2610
2611 fn parse_expr_cond(&mut self) -> PResult<'a, P<Expr>> {
2613 let attrs = self.parse_outer_attributes()?;
2614 let (mut cond, _) =
2615 self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, attrs)?;
2616
2617 CondChecker::new(self).visit_expr(&mut cond);
2618
2619 if let ExprKind::Let(_, _, _, Recovered::No) = cond.kind {
2620 self.psess.gated_spans.ungate_last(sym::let_chains, cond.span);
2622 }
2623
2624 Ok(cond)
2625 }
2626
2627 fn parse_expr_let(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> {
2629 let recovered = if !restrictions.contains(Restrictions::ALLOW_LET) {
2630 let err = errors::ExpectedExpressionFoundLet {
2631 span: self.token.span,
2632 reason: ForbiddenLetReason::OtherForbidden,
2633 missing_let: None,
2634 comparison: None,
2635 };
2636 if self.prev_token == token::BinOp(token::Or) {
2637 return Err(self.dcx().create_err(err));
2639 } else {
2640 Recovered::Yes(self.dcx().emit_err(err))
2641 }
2642 } else {
2643 Recovered::No
2644 };
2645 self.bump(); let lo = self.prev_token.span;
2647 let pat = self.parse_pat_no_top_guard(
2648 None,
2649 RecoverComma::Yes,
2650 RecoverColon::Yes,
2651 CommaRecoveryMode::LikelyTuple,
2652 )?;
2653 if self.token == token::EqEq {
2654 self.dcx().emit_err(errors::ExpectedEqForLetExpr {
2655 span: self.token.span,
2656 sugg_span: self.token.span,
2657 });
2658 self.bump();
2659 } else {
2660 self.expect(exp!(Eq))?;
2661 }
2662 let attrs = self.parse_outer_attributes()?;
2663 let (expr, _) =
2664 self.parse_expr_assoc_with(Bound::Excluded(prec_let_scrutinee_needs_par()), attrs)?;
2665 let span = lo.to(expr.span);
2666 Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, recovered)))
2667 }
2668
2669 fn parse_expr_else(&mut self) -> PResult<'a, P<Expr>> {
2671 let else_span = self.prev_token.span; let attrs = self.parse_outer_attributes()?; let expr = if self.eat_keyword(exp!(If)) {
2674 ensure_sufficient_stack(|| self.parse_expr_if())?
2675 } else if self.check(exp!(OpenBrace)) {
2676 self.parse_simple_block()?
2677 } else {
2678 let snapshot = self.create_snapshot_for_diagnostic();
2679 let first_tok = super::token_descr(&self.token);
2680 let first_tok_span = self.token.span;
2681 match self.parse_expr() {
2682 Ok(cond)
2683 if self.check(exp!(OpenBrace))
2718 && (classify::expr_requires_semi_to_be_stmt(&cond)
2719 || matches!(cond.kind, ExprKind::MacCall(..)))
2720 =>
2721 {
2722 self.dcx().emit_err(errors::ExpectedElseBlock {
2723 first_tok_span,
2724 first_tok,
2725 else_span,
2726 condition_start: cond.span.shrink_to_lo(),
2727 });
2728 self.parse_if_after_cond(cond.span.shrink_to_lo(), cond)?
2729 }
2730 Err(e) => {
2731 e.cancel();
2732 self.restore_snapshot(snapshot);
2733 self.parse_simple_block()?
2734 },
2735 Ok(_) => {
2736 self.restore_snapshot(snapshot);
2737 self.parse_simple_block()?
2738 },
2739 }
2740 };
2741 self.error_on_if_block_attrs(else_span, true, expr.span, attrs);
2742 Ok(expr)
2743 }
2744
2745 fn error_on_if_block_attrs(
2746 &self,
2747 ctx_span: Span,
2748 is_ctx_else: bool,
2749 branch_span: Span,
2750 attrs: AttrWrapper,
2751 ) {
2752 if !attrs.is_empty()
2753 && let [x0 @ xn] | [x0, .., xn] = &*attrs.take_for_recovery(self.psess)
2754 {
2755 let attributes = x0.span.until(branch_span);
2756 let last = xn.span;
2757 let ctx = if is_ctx_else { "else" } else { "if" };
2758 self.dcx().emit_err(errors::OuterAttributeNotAllowedOnIfElse {
2759 last,
2760 branch_span,
2761 ctx_span,
2762 ctx: ctx.to_string(),
2763 attributes,
2764 });
2765 }
2766 }
2767
2768 fn error_on_extra_if(&mut self, cond: &P<Expr>) -> PResult<'a, ()> {
2769 if let ExprKind::Binary(Spanned { span: binop_span, node: binop }, _, right) = &cond.kind
2770 && let BinOpKind::And = binop
2771 && let ExprKind::If(cond, ..) = &right.kind
2772 {
2773 Err(self.dcx().create_err(errors::UnexpectedIfWithIf(
2774 binop_span.shrink_to_hi().to(cond.span.shrink_to_lo()),
2775 )))
2776 } else {
2777 Ok(())
2778 }
2779 }
2780
2781 fn parse_for_head(&mut self) -> PResult<'a, (P<Pat>, P<Expr>)> {
2782 let begin_paren = if self.token == token::OpenDelim(Delimiter::Parenthesis) {
2783 let start_span = self.token.span;
2787 let left = self.prev_token.span.between(self.look_ahead(1, |t| t.span));
2788 Some((start_span, left))
2789 } else {
2790 None
2791 };
2792 let pat = match (
2794 self.parse_pat_allow_top_guard(
2795 None,
2796 RecoverComma::Yes,
2797 RecoverColon::Yes,
2798 CommaRecoveryMode::LikelyTuple,
2799 ),
2800 begin_paren,
2801 ) {
2802 (Ok(pat), _) => pat, (Err(err), Some((start_span, left))) if self.eat_keyword(exp!(In)) => {
2804 let attrs = self.parse_outer_attributes()?;
2807 let (expr, _) = match self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs) {
2808 Ok(expr) => expr,
2809 Err(expr_err) => {
2810 expr_err.cancel();
2813 return Err(err);
2814 }
2815 };
2816 return if self.token == token::CloseDelim(Delimiter::Parenthesis) {
2817 let span = vec![start_span, self.token.span];
2820 let right = self.prev_token.span.between(self.look_ahead(1, |t| t.span));
2821 self.bump(); err.cancel();
2823 self.dcx().emit_err(errors::ParenthesesInForHead {
2824 span,
2825 sugg: errors::ParenthesesInForHeadSugg { left, right },
2829 });
2830 Ok((self.mk_pat(start_span.to(right), ast::PatKind::Wild), expr))
2831 } else {
2832 Err(err) };
2834 }
2835 (Err(err), _) => return Err(err), };
2837 if !self.eat_keyword(exp!(In)) {
2838 self.error_missing_in_for_loop();
2839 }
2840 self.check_for_for_in_in_typo(self.prev_token.span);
2841 let attrs = self.parse_outer_attributes()?;
2842 let (expr, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs)?;
2843 Ok((pat, expr))
2844 }
2845
2846 fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
2848 let is_await =
2849 self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await));
2850
2851 if is_await {
2852 self.psess.gated_spans.gate(sym::async_for_loop, self.prev_token.span);
2853 }
2854
2855 let kind = if is_await { ForLoopKind::ForAwait } else { ForLoopKind::For };
2856
2857 let (pat, expr) = self.parse_for_head()?;
2858 if matches!(expr.kind, ExprKind::Block(..))
2860 && !matches!(self.token.kind, token::OpenDelim(Delimiter::Brace))
2861 && self.may_recover()
2862 {
2863 let guar = self
2864 .dcx()
2865 .emit_err(errors::MissingExpressionInForLoop { span: expr.span.shrink_to_lo() });
2866 let err_expr = self.mk_expr(expr.span, ExprKind::Err(guar));
2867 let block = self.mk_block(thin_vec![], BlockCheckMode::Default, self.prev_token.span);
2868 return Ok(self.mk_expr(
2869 lo.to(self.prev_token.span),
2870 ExprKind::ForLoop { pat, iter: err_expr, body: block, label: opt_label, kind },
2871 ));
2872 }
2873
2874 let (attrs, loop_block) = self.parse_inner_attrs_and_block()?;
2875
2876 let kind = ExprKind::ForLoop { pat, iter: expr, body: loop_block, label: opt_label, kind };
2877
2878 self.recover_loop_else("for", lo)?;
2879
2880 Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
2881 }
2882
2883 fn recover_loop_else(&mut self, loop_kind: &'static str, loop_kw: Span) -> PResult<'a, ()> {
2885 if self.token.is_keyword(kw::Else) && self.may_recover() {
2886 let else_span = self.token.span;
2887 self.bump();
2888 let else_clause = self.parse_expr_else()?;
2889 self.dcx().emit_err(errors::LoopElseNotSupported {
2890 span: else_span.to(else_clause.span),
2891 loop_kind,
2892 loop_kw,
2893 });
2894 }
2895 Ok(())
2896 }
2897
2898 fn error_missing_in_for_loop(&mut self) {
2899 let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) {
2900 let span = self.token.span;
2902 self.bump();
2903 (span, errors::MissingInInForLoopSub::InNotOf)
2904 } else {
2905 (self.prev_token.span.between(self.token.span), errors::MissingInInForLoopSub::AddIn)
2906 };
2907
2908 self.dcx().emit_err(errors::MissingInInForLoop { span, sub: sub(span) });
2909 }
2910
2911 fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
2913 let cond = self.parse_expr_cond().map_err(|mut err| {
2914 err.span_label(lo, "while parsing the condition of this `while` expression");
2915 err
2916 })?;
2917 let (attrs, body) = self.parse_inner_attrs_and_block().map_err(|mut err| {
2918 err.span_label(lo, "while parsing the body of this `while` expression");
2919 err.span_label(cond.span, "this `while` condition successfully parsed");
2920 err
2921 })?;
2922
2923 self.recover_loop_else("while", lo)?;
2924
2925 Ok(self.mk_expr_with_attrs(
2926 lo.to(self.prev_token.span),
2927 ExprKind::While(cond, body, opt_label),
2928 attrs,
2929 ))
2930 }
2931
2932 fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
2934 let loop_span = self.prev_token.span;
2935 let (attrs, body) = self.parse_inner_attrs_and_block()?;
2936 self.recover_loop_else("loop", lo)?;
2937 Ok(self.mk_expr_with_attrs(
2938 lo.to(self.prev_token.span),
2939 ExprKind::Loop(body, opt_label, loop_span),
2940 attrs,
2941 ))
2942 }
2943
2944 pub(crate) fn eat_label(&mut self) -> Option<Label> {
2945 if let Some((ident, is_raw)) = self.token.lifetime() {
2946 if matches!(is_raw, IdentIsRaw::No) && ident.without_first_quote().is_reserved() {
2948 self.dcx().emit_err(errors::InvalidLabel { span: ident.span, name: ident.name });
2949 }
2950
2951 self.bump();
2952 Some(Label { ident })
2953 } else {
2954 None
2955 }
2956 }
2957
2958 fn parse_expr_match(&mut self) -> PResult<'a, P<Expr>> {
2960 let match_span = self.prev_token.span;
2961 let attrs = self.parse_outer_attributes()?;
2962 let (scrutinee, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs)?;
2963
2964 self.parse_match_block(match_span, match_span, scrutinee, MatchKind::Prefix)
2965 }
2966
2967 fn parse_match_block(
2970 &mut self,
2971 lo: Span,
2972 match_span: Span,
2973 scrutinee: P<Expr>,
2974 match_kind: MatchKind,
2975 ) -> PResult<'a, P<Expr>> {
2976 if let Err(mut e) = self.expect(exp!(OpenBrace)) {
2977 if self.token == token::Semi {
2978 e.span_suggestion_short(
2979 match_span,
2980 "try removing this `match`",
2981 "",
2982 Applicability::MaybeIncorrect, );
2984 }
2985 if self.maybe_recover_unexpected_block_label() {
2986 e.cancel();
2987 self.bump();
2988 } else {
2989 return Err(e);
2990 }
2991 }
2992 let attrs = self.parse_inner_attributes()?;
2993
2994 let mut arms = ThinVec::new();
2995 while self.token != token::CloseDelim(Delimiter::Brace) {
2996 match self.parse_arm() {
2997 Ok(arm) => arms.push(arm),
2998 Err(e) => {
2999 let guar = e.emit();
3001 self.recover_stmt();
3002 let span = lo.to(self.token.span);
3003 if self.token == token::CloseDelim(Delimiter::Brace) {
3004 self.bump();
3005 }
3006 arms.push(Arm {
3008 attrs: Default::default(),
3009 pat: self.mk_pat(span, ast::PatKind::Err(guar)),
3010 guard: None,
3011 body: Some(self.mk_expr_err(span, guar)),
3012 span,
3013 id: DUMMY_NODE_ID,
3014 is_placeholder: false,
3015 });
3016 return Ok(self.mk_expr_with_attrs(
3017 span,
3018 ExprKind::Match(scrutinee, arms, match_kind),
3019 attrs,
3020 ));
3021 }
3022 }
3023 }
3024 let hi = self.token.span;
3025 self.bump();
3026 Ok(self.mk_expr_with_attrs(lo.to(hi), ExprKind::Match(scrutinee, arms, match_kind), attrs))
3027 }
3028
3029 fn parse_arm_body_missing_braces(
3031 &mut self,
3032 first_expr: &P<Expr>,
3033 arrow_span: Span,
3034 ) -> Option<(Span, ErrorGuaranteed)> {
3035 if self.token != token::Semi {
3036 return None;
3037 }
3038 let start_snapshot = self.create_snapshot_for_diagnostic();
3039 let semi_sp = self.token.span;
3040 self.bump(); let mut stmts =
3042 vec![self.mk_stmt(first_expr.span, ast::StmtKind::Expr(first_expr.clone()))];
3043 let err = |this: &Parser<'_>, stmts: Vec<ast::Stmt>| {
3044 let span = stmts[0].span.to(stmts[stmts.len() - 1].span);
3045
3046 let guar = this.dcx().emit_err(errors::MatchArmBodyWithoutBraces {
3047 statements: span,
3048 arrow: arrow_span,
3049 num_statements: stmts.len(),
3050 sub: if stmts.len() > 1 {
3051 errors::MatchArmBodyWithoutBracesSugg::AddBraces {
3052 left: span.shrink_to_lo(),
3053 right: span.shrink_to_hi(),
3054 }
3055 } else {
3056 errors::MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp }
3057 },
3058 });
3059 (span, guar)
3060 };
3061 loop {
3064 if self.token == token::CloseDelim(Delimiter::Brace) {
3065 return Some(err(self, stmts));
3067 }
3068 if self.token == token::Comma {
3069 self.restore_snapshot(start_snapshot);
3070 return None;
3071 }
3072 let pre_pat_snapshot = self.create_snapshot_for_diagnostic();
3073 match self.parse_pat_no_top_alt(None, None) {
3074 Ok(_pat) => {
3075 if self.token == token::FatArrow {
3076 self.restore_snapshot(pre_pat_snapshot);
3078 return Some(err(self, stmts));
3079 }
3080 }
3081 Err(err) => {
3082 err.cancel();
3083 }
3084 }
3085
3086 self.restore_snapshot(pre_pat_snapshot);
3087 match self.parse_stmt_without_recovery(true, ForceCollect::No) {
3088 Ok(Some(stmt)) => {
3090 stmts.push(stmt);
3091 }
3092 Ok(None) => {
3093 self.restore_snapshot(start_snapshot);
3094 break;
3095 }
3096 Err(stmt_err) => {
3099 stmt_err.cancel();
3100 self.restore_snapshot(start_snapshot);
3101 break;
3102 }
3103 }
3104 }
3105 None
3106 }
3107
3108 pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
3109 let attrs = self.parse_outer_attributes()?;
3110 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
3111 let lo = this.token.span;
3112 let (pat, guard) = this.parse_match_arm_pat_and_guard()?;
3113
3114 let span_before_body = this.prev_token.span;
3115 let arm_body;
3116 let is_fat_arrow = this.check(exp!(FatArrow));
3117 let is_almost_fat_arrow =
3118 TokenKind::FatArrow.similar_tokens().contains(&this.token.kind);
3119
3120 let armless = (!is_fat_arrow && !is_almost_fat_arrow && pat.could_be_never_pattern())
3123 || matches!(this.token.kind, token::Comma | token::CloseDelim(Delimiter::Brace));
3124
3125 let mut result = if armless {
3126 arm_body = None;
3128 this.expect_one_of(&[exp!(Comma)], &[exp!(CloseBrace)]).map(|x| {
3129 if !pat.contains_never_pattern() {
3131 this.psess.gated_spans.gate(sym::never_patterns, pat.span);
3132 }
3133 x
3134 })
3135 } else {
3136 if let Err(mut err) = this.expect(exp!(FatArrow)) {
3137 if is_almost_fat_arrow {
3139 err.span_suggestion(
3140 this.token.span,
3141 "use a fat arrow to start a match arm",
3142 "=>",
3143 Applicability::MachineApplicable,
3144 );
3145 if matches!(
3146 (&this.prev_token.kind, &this.token.kind),
3147 (token::DotDotEq, token::Gt)
3148 ) {
3149 err.delay_as_bug();
3152 } else {
3153 err.emit();
3154 }
3155 this.bump();
3156 } else {
3157 return Err(err);
3158 }
3159 }
3160 let arrow_span = this.prev_token.span;
3161 let arm_start_span = this.token.span;
3162
3163 let attrs = this.parse_outer_attributes()?;
3164 let (expr, _) =
3165 this.parse_expr_res(Restrictions::STMT_EXPR, attrs).map_err(|mut err| {
3166 err.span_label(arrow_span, "while parsing the `match` arm starting here");
3167 err
3168 })?;
3169
3170 let require_comma = !classify::expr_is_complete(&expr)
3171 && this.token != token::CloseDelim(Delimiter::Brace);
3172
3173 if !require_comma {
3174 arm_body = Some(expr);
3175 let _ = this.eat(exp!(Comma));
3177 Ok(Recovered::No)
3178 } else if let Some((span, guar)) =
3179 this.parse_arm_body_missing_braces(&expr, arrow_span)
3180 {
3181 let body = this.mk_expr_err(span, guar);
3182 arm_body = Some(body);
3183 Ok(Recovered::Yes(guar))
3184 } else {
3185 let expr_span = expr.span;
3186 arm_body = Some(expr);
3187 this.expect_one_of(&[exp!(Comma)], &[exp!(CloseBrace)]).map_err(|mut err| {
3188 if this.token == token::FatArrow {
3189 let sm = this.psess.source_map();
3190 if let Ok(expr_lines) = sm.span_to_lines(expr_span)
3191 && let Ok(arm_start_lines) = sm.span_to_lines(arm_start_span)
3192 && arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col
3193 && expr_lines.lines.len() == 2
3194 {
3195 err.span_suggestion_short(
3207 arm_start_span.shrink_to_hi(),
3208 "missing a comma here to end this `match` arm",
3209 ",",
3210 Applicability::MachineApplicable,
3211 );
3212 }
3213 } else {
3214 err.span_label(
3215 arrow_span,
3216 "while parsing the `match` arm starting here",
3217 );
3218 }
3219 err
3220 })
3221 }
3222 };
3223
3224 let hi_span = arm_body.as_ref().map_or(span_before_body, |body| body.span);
3225 let arm_span = lo.to(hi_span);
3226
3227 let recover_missing_comma = arm_body.is_some() || pat.could_be_never_pattern();
3241 if recover_missing_comma {
3242 result = result.or_else(|err| {
3243 let mut snapshot = this.create_snapshot_for_diagnostic();
3248 let pattern_follows = snapshot
3249 .parse_pat_no_top_guard(
3250 None,
3251 RecoverComma::Yes,
3252 RecoverColon::Yes,
3253 CommaRecoveryMode::EitherTupleOrPipe,
3254 )
3255 .map_err(|err| err.cancel())
3256 .is_ok();
3257 if pattern_follows && snapshot.check(exp!(FatArrow)) {
3258 err.cancel();
3259 let guar = this.dcx().emit_err(errors::MissingCommaAfterMatchArm {
3260 span: arm_span.shrink_to_hi(),
3261 });
3262 return Ok(Recovered::Yes(guar));
3263 }
3264 Err(err)
3265 });
3266 }
3267 result?;
3268
3269 Ok((
3270 ast::Arm {
3271 attrs,
3272 pat,
3273 guard,
3274 body: arm_body,
3275 span: arm_span,
3276 id: DUMMY_NODE_ID,
3277 is_placeholder: false,
3278 },
3279 Trailing::No,
3280 UsePreAttrPos::No,
3281 ))
3282 })
3283 }
3284
3285 fn parse_match_arm_guard(&mut self) -> PResult<'a, Option<P<Expr>>> {
3286 fn check_let_expr(expr: &Expr) -> (bool, bool) {
3289 match &expr.kind {
3290 ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, lhs, rhs) => {
3291 let lhs_rslt = check_let_expr(lhs);
3292 let rhs_rslt = check_let_expr(rhs);
3293 (lhs_rslt.0 || rhs_rslt.0, false)
3294 }
3295 ExprKind::Let(..) => (true, true),
3296 _ => (false, true),
3297 }
3298 }
3299 if !self.eat_keyword(exp!(If)) {
3300 return Ok(None);
3302 }
3303
3304 let if_span = self.prev_token.span;
3305 let mut cond = self.parse_match_guard_condition()?;
3306
3307 CondChecker::new(self).visit_expr(&mut cond);
3308
3309 let (has_let_expr, does_not_have_bin_op) = check_let_expr(&cond);
3310 if has_let_expr {
3311 if does_not_have_bin_op {
3312 self.psess.gated_spans.ungate_last(sym::let_chains, cond.span);
3314 }
3315 let span = if_span.to(cond.span);
3316 self.psess.gated_spans.gate(sym::if_let_guard, span);
3317 }
3318 Ok(Some(cond))
3319 }
3320
3321 fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (P<Pat>, Option<P<Expr>>)> {
3322 if self.token == token::OpenDelim(Delimiter::Parenthesis) {
3323 let left = self.token.span;
3324 let pat = self.parse_pat_no_top_guard(
3325 None,
3326 RecoverComma::Yes,
3327 RecoverColon::Yes,
3328 CommaRecoveryMode::EitherTupleOrPipe,
3329 )?;
3330 if let ast::PatKind::Paren(subpat) = &pat.kind
3331 && let ast::PatKind::Guard(..) = &subpat.kind
3332 {
3333 let span = pat.span;
3336 let ast::PatKind::Paren(subpat) = pat.into_inner().kind else { unreachable!() };
3337 let ast::PatKind::Guard(_, mut cond) = subpat.into_inner().kind else {
3338 unreachable!()
3339 };
3340 self.psess.gated_spans.ungate_last(sym::guard_patterns, cond.span);
3341 CondChecker::new(self).visit_expr(&mut cond);
3342 let right = self.prev_token.span;
3343 self.dcx().emit_err(errors::ParenthesesInMatchPat {
3344 span: vec![left, right],
3345 sugg: errors::ParenthesesInMatchPatSugg { left, right },
3346 });
3347 Ok((self.mk_pat(span, ast::PatKind::Wild), Some(cond)))
3348 } else {
3349 Ok((pat, self.parse_match_arm_guard()?))
3350 }
3351 } else {
3352 let pat = self.parse_pat_no_top_guard(
3354 None,
3355 RecoverComma::Yes,
3356 RecoverColon::Yes,
3357 CommaRecoveryMode::EitherTupleOrPipe,
3358 )?;
3359 Ok((pat, self.parse_match_arm_guard()?))
3360 }
3361 }
3362
3363 fn parse_match_guard_condition(&mut self) -> PResult<'a, P<Expr>> {
3364 let attrs = self.parse_outer_attributes()?;
3365 match self.parse_expr_res(Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD, attrs) {
3366 Ok((expr, _)) => Ok(expr),
3367 Err(mut err) => {
3368 if self.prev_token == token::OpenDelim(Delimiter::Brace) {
3369 let sugg_sp = self.prev_token.span.shrink_to_lo();
3370 self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
3373 let msg = "you might have meant to start a match arm after the match guard";
3374 if self.eat(exp!(CloseBrace)) {
3375 let applicability = if self.token != token::FatArrow {
3376 Applicability::MachineApplicable
3381 } else {
3382 Applicability::MaybeIncorrect
3383 };
3384 err.span_suggestion_verbose(sugg_sp, msg, "=> ", applicability);
3385 }
3386 }
3387 Err(err)
3388 }
3389 }
3390 }
3391
3392 pub(crate) fn is_builtin(&self) -> bool {
3393 self.token.is_keyword(kw::Builtin) && self.look_ahead(1, |t| *t == token::Pound)
3394 }
3395
3396 fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> {
3398 let (attrs, body) = self.parse_inner_attrs_and_block()?;
3399 if self.eat_keyword(exp!(Catch)) {
3400 Err(self.dcx().create_err(errors::CatchAfterTry { span: self.prev_token.span }))
3401 } else {
3402 let span = span_lo.to(body.span);
3403 self.psess.gated_spans.gate(sym::try_blocks, span);
3404 Ok(self.mk_expr_with_attrs(span, ExprKind::TryBlock(body), attrs))
3405 }
3406 }
3407
3408 fn is_do_catch_block(&self) -> bool {
3409 self.token.is_keyword(kw::Do)
3410 && self.is_keyword_ahead(1, &[kw::Catch])
3411 && self
3412 .look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block())
3413 && !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
3414 }
3415
3416 fn is_do_yeet(&self) -> bool {
3417 self.token.is_keyword(kw::Do) && self.is_keyword_ahead(1, &[kw::Yeet])
3418 }
3419
3420 fn is_try_block(&self) -> bool {
3421 self.token.is_keyword(kw::Try)
3422 && self
3423 .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block())
3424 && self.token.uninterpolated_span().at_least_rust_2018()
3425 }
3426
3427 fn parse_gen_block(&mut self) -> PResult<'a, P<Expr>> {
3429 let lo = self.token.span;
3430 let kind = if self.eat_keyword(exp!(Async)) {
3431 if self.eat_keyword(exp!(Gen)) { GenBlockKind::AsyncGen } else { GenBlockKind::Async }
3432 } else {
3433 assert!(self.eat_keyword(exp!(Gen)));
3434 GenBlockKind::Gen
3435 };
3436 match kind {
3437 GenBlockKind::Async => {
3438 }
3440 GenBlockKind::Gen | GenBlockKind::AsyncGen => {
3441 self.psess.gated_spans.gate(sym::gen_blocks, lo.to(self.prev_token.span));
3442 }
3443 }
3444 let capture_clause = self.parse_capture_clause()?;
3445 let decl_span = lo.to(self.prev_token.span);
3446 let (attrs, body) = self.parse_inner_attrs_and_block()?;
3447 let kind = ExprKind::Gen(capture_clause, body, kind, decl_span);
3448 Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
3449 }
3450
3451 fn is_gen_block(&self, kw: Symbol, lookahead: usize) -> bool {
3452 self.is_keyword_ahead(lookahead, &[kw])
3453 && ((
3454 self.is_keyword_ahead(lookahead + 1, &[kw::Move])
3456 && self.look_ahead(lookahead + 2, |t| {
3457 *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block()
3458 })
3459 ) || (
3460 self.look_ahead(lookahead + 1, |t| {
3462 *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block()
3463 })
3464 ))
3465 }
3466
3467 pub(super) fn is_async_gen_block(&self) -> bool {
3468 self.token.is_keyword(kw::Async) && self.is_gen_block(kw::Gen, 1)
3469 }
3470
3471 fn is_certainly_not_a_block(&self) -> bool {
3472 self.look_ahead(1, |t| t.is_ident())
3473 && (
3474 self.look_ahead(2, |t| t == &token::Comma)
3476 || self.look_ahead(2, |t| t == &token::Colon)
3477 && (
3478 self.look_ahead(4, |t| t == &token::Comma)
3480 || self.look_ahead(3, |t| !t.can_begin_type())
3483 )
3484 )
3485 }
3486
3487 fn maybe_parse_struct_expr(
3488 &mut self,
3489 qself: &Option<P<ast::QSelf>>,
3490 path: &ast::Path,
3491 ) -> Option<PResult<'a, P<Expr>>> {
3492 let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
3493 if struct_allowed || self.is_certainly_not_a_block() {
3494 if let Err(err) = self.expect(exp!(OpenBrace)) {
3495 return Some(Err(err));
3496 }
3497 let expr = self.parse_expr_struct(qself.clone(), path.clone(), true);
3498 if let (Ok(expr), false) = (&expr, struct_allowed) {
3499 self.dcx().emit_err(errors::StructLiteralNotAllowedHere {
3501 span: expr.span,
3502 sub: errors::StructLiteralNotAllowedHereSugg {
3503 left: path.span.shrink_to_lo(),
3504 right: expr.span.shrink_to_hi(),
3505 },
3506 });
3507 }
3508 return Some(expr);
3509 }
3510 None
3511 }
3512
3513 pub(super) fn parse_struct_fields(
3514 &mut self,
3515 pth: ast::Path,
3516 recover: bool,
3517 close: ExpTokenPair<'_>,
3518 ) -> PResult<
3519 'a,
3520 (
3521 ThinVec<ExprField>,
3522 ast::StructRest,
3523 Option<ErrorGuaranteed>, ),
3525 > {
3526 let mut fields = ThinVec::new();
3527 let mut base = ast::StructRest::None;
3528 let mut recovered_async = None;
3529 let in_if_guard = self.restrictions.contains(Restrictions::IN_IF_GUARD);
3530
3531 let async_block_err = |e: &mut Diag<'_>, span: Span| {
3532 errors::AsyncBlockIn2015 { span }.add_to_diag(e);
3533 errors::HelpUseLatestEdition::new().add_to_diag(e);
3534 };
3535
3536 while self.token != *close.tok {
3537 if self.eat(exp!(DotDot)) || self.recover_struct_field_dots(close.tok) {
3538 let exp_span = self.prev_token.span;
3539 if self.check(close) {
3541 base = ast::StructRest::Rest(self.prev_token.span);
3542 break;
3543 }
3544 match self.parse_expr() {
3545 Ok(e) => base = ast::StructRest::Base(e),
3546 Err(e) if recover => {
3547 e.emit();
3548 self.recover_stmt();
3549 }
3550 Err(e) => return Err(e),
3551 }
3552 self.recover_struct_comma_after_dotdot(exp_span);
3553 break;
3554 }
3555
3556 let peek = self
3558 .token
3559 .ident()
3560 .filter(|(ident, is_raw)| {
3561 (!ident.is_reserved() || matches!(is_raw, IdentIsRaw::Yes))
3562 && self.look_ahead(1, |tok| *tok == token::Colon)
3563 })
3564 .map(|(ident, _)| ident);
3565
3566 let field_ident = |this: &Self, guar: ErrorGuaranteed| {
3568 peek.map(|ident| {
3569 let span = ident.span;
3570 ExprField {
3571 ident,
3572 span,
3573 expr: this.mk_expr_err(span, guar),
3574 is_shorthand: false,
3575 attrs: AttrVec::new(),
3576 id: DUMMY_NODE_ID,
3577 is_placeholder: false,
3578 }
3579 })
3580 };
3581
3582 let parsed_field = match self.parse_expr_field() {
3583 Ok(f) => Ok(f),
3584 Err(mut e) => {
3585 if pth == kw::Async {
3586 async_block_err(&mut e, pth.span);
3587 } else {
3588 e.span_label(pth.span, "while parsing this struct");
3589 }
3590
3591 if let Some((ident, _)) = self.token.ident()
3592 && !self.token.is_reserved_ident()
3593 && self.look_ahead(1, |t| {
3594 AssocOp::from_token(t).is_some()
3595 || matches!(
3596 t.kind,
3597 token::OpenDelim(
3598 Delimiter::Parenthesis
3599 | Delimiter::Bracket
3600 | Delimiter::Brace
3601 )
3602 )
3603 || *t == token::Dot
3604 })
3605 {
3606 e.span_suggestion_verbose(
3609 self.token.span.shrink_to_lo(),
3610 "try naming a field",
3611 &format!("{ident}: ",),
3612 Applicability::MaybeIncorrect,
3613 );
3614 }
3615 if in_if_guard && close.token_type == TokenType::CloseBrace {
3616 return Err(e);
3617 }
3618
3619 if !recover {
3620 return Err(e);
3621 }
3622
3623 let guar = e.emit();
3624 if pth == kw::Async {
3625 recovered_async = Some(guar);
3626 }
3627
3628 if self.token != token::Comma {
3632 self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
3633 if self.token != token::Comma {
3634 break;
3635 }
3636 }
3637
3638 Err(guar)
3639 }
3640 };
3641
3642 let is_shorthand = parsed_field.as_ref().is_ok_and(|f| f.is_shorthand);
3643 self.check_or_expected(!is_shorthand, TokenType::Colon);
3646
3647 match self.expect_one_of(&[exp!(Comma)], &[close]) {
3648 Ok(_) => {
3649 if let Ok(f) = parsed_field.or_else(|guar| field_ident(self, guar).ok_or(guar))
3650 {
3651 fields.push(f);
3653 }
3654 }
3655 Err(mut e) => {
3656 if pth == kw::Async {
3657 async_block_err(&mut e, pth.span);
3658 } else {
3659 e.span_label(pth.span, "while parsing this struct");
3660 if peek.is_some() {
3661 e.span_suggestion(
3662 self.prev_token.span.shrink_to_hi(),
3663 "try adding a comma",
3664 ",",
3665 Applicability::MachineApplicable,
3666 );
3667 }
3668 }
3669 if !recover {
3670 return Err(e);
3671 }
3672 let guar = e.emit();
3673 if pth == kw::Async {
3674 recovered_async = Some(guar);
3675 } else if let Some(f) = field_ident(self, guar) {
3676 fields.push(f);
3677 }
3678 self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
3679 let _ = self.eat(exp!(Comma));
3680 }
3681 }
3682 }
3683 Ok((fields, base, recovered_async))
3684 }
3685
3686 pub(super) fn parse_expr_struct(
3688 &mut self,
3689 qself: Option<P<ast::QSelf>>,
3690 pth: ast::Path,
3691 recover: bool,
3692 ) -> PResult<'a, P<Expr>> {
3693 let lo = pth.span;
3694 let (fields, base, recovered_async) =
3695 self.parse_struct_fields(pth.clone(), recover, exp!(CloseBrace))?;
3696 let span = lo.to(self.token.span);
3697 self.expect(exp!(CloseBrace))?;
3698 let expr = if let Some(guar) = recovered_async {
3699 ExprKind::Err(guar)
3700 } else {
3701 ExprKind::Struct(P(ast::StructExpr { qself, path: pth, fields, rest: base }))
3702 };
3703 Ok(self.mk_expr(span, expr))
3704 }
3705
3706 fn recover_struct_comma_after_dotdot(&mut self, span: Span) {
3707 if self.token != token::Comma {
3708 return;
3709 }
3710 self.dcx().emit_err(errors::CommaAfterBaseStruct {
3711 span: span.to(self.prev_token.span),
3712 comma: self.token.span,
3713 });
3714 self.recover_stmt();
3715 }
3716
3717 fn recover_struct_field_dots(&mut self, close: &TokenKind) -> bool {
3718 if !self.look_ahead(1, |t| t == close) && self.eat(exp!(DotDotDot)) {
3719 let span = self.prev_token.span;
3721 self.dcx().emit_err(errors::MissingDotDot { token_span: span, sugg_span: span });
3722 return true;
3723 }
3724 false
3725 }
3726
3727 fn recover_ident_into_label(&mut self, ident: Ident) -> Label {
3729 let label = format!("'{}", ident.name);
3732 let ident = Ident { name: Symbol::intern(&label), span: ident.span };
3733
3734 self.dcx().emit_err(errors::ExpectedLabelFoundIdent {
3735 span: ident.span,
3736 start: ident.span.shrink_to_lo(),
3737 });
3738
3739 Label { ident }
3740 }
3741
3742 fn parse_expr_field(&mut self) -> PResult<'a, ExprField> {
3744 let attrs = self.parse_outer_attributes()?;
3745 self.recover_vcs_conflict_marker();
3746 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
3747 let lo = this.token.span;
3748
3749 let is_shorthand = !this.look_ahead(1, |t| t == &token::Colon || t == &token::Eq);
3751 let is_wrong = this.token.is_ident()
3753 && !this.token.is_reserved_ident()
3754 && !this.look_ahead(1, |t| {
3755 t == &token::Colon
3756 || t == &token::Eq
3757 || t == &token::Comma
3758 || t == &token::CloseDelim(Delimiter::Brace)
3759 || t == &token::CloseDelim(Delimiter::Parenthesis)
3760 });
3761 if is_wrong {
3762 return Err(this.dcx().create_err(errors::ExpectedStructField {
3763 span: this.look_ahead(1, |t| t.span),
3764 ident_span: this.token.span,
3765 token: this.look_ahead(1, |t| t.clone()),
3766 }));
3767 }
3768 let (ident, expr) = if is_shorthand {
3769 let ident = this.parse_ident_common(false)?;
3771 let path = ast::Path::from_ident(ident);
3772 (ident, this.mk_expr(ident.span, ExprKind::Path(None, path)))
3773 } else {
3774 let ident = this.parse_field_name()?;
3775 this.error_on_eq_field_init(ident);
3776 this.bump(); (ident, this.parse_expr()?)
3778 };
3779
3780 Ok((
3781 ast::ExprField {
3782 ident,
3783 span: lo.to(expr.span),
3784 expr,
3785 is_shorthand,
3786 attrs,
3787 id: DUMMY_NODE_ID,
3788 is_placeholder: false,
3789 },
3790 Trailing::from(this.token == token::Comma),
3791 UsePreAttrPos::No,
3792 ))
3793 })
3794 }
3795
3796 fn error_on_eq_field_init(&self, field_name: Ident) {
3799 if self.token != token::Eq {
3800 return;
3801 }
3802
3803 self.dcx().emit_err(errors::EqFieldInit {
3804 span: self.token.span,
3805 eq: field_name.span.shrink_to_hi().to(self.token.span),
3806 });
3807 }
3808
3809 fn err_dotdotdot_syntax(&self, span: Span) {
3810 self.dcx().emit_err(errors::DotDotDot { span });
3811 }
3812
3813 fn err_larrow_operator(&self, span: Span) {
3814 self.dcx().emit_err(errors::LeftArrowOperator { span });
3815 }
3816
3817 fn mk_assign_op(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind {
3818 ExprKind::AssignOp(binop, lhs, rhs)
3819 }
3820
3821 fn mk_range(
3822 &mut self,
3823 start: Option<P<Expr>>,
3824 end: Option<P<Expr>>,
3825 limits: RangeLimits,
3826 ) -> ExprKind {
3827 if end.is_none() && limits == RangeLimits::Closed {
3828 let guar = self.inclusive_range_with_incorrect_end();
3829 ExprKind::Err(guar)
3830 } else {
3831 ExprKind::Range(start, end, limits)
3832 }
3833 }
3834
3835 fn mk_unary(&self, unop: UnOp, expr: P<Expr>) -> ExprKind {
3836 ExprKind::Unary(unop, expr)
3837 }
3838
3839 fn mk_binary(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind {
3840 ExprKind::Binary(binop, lhs, rhs)
3841 }
3842
3843 fn mk_index(&self, expr: P<Expr>, idx: P<Expr>, brackets_span: Span) -> ExprKind {
3844 ExprKind::Index(expr, idx, brackets_span)
3845 }
3846
3847 fn mk_call(&self, f: P<Expr>, args: ThinVec<P<Expr>>) -> ExprKind {
3848 ExprKind::Call(f, args)
3849 }
3850
3851 fn mk_await_expr(&mut self, self_arg: P<Expr>, lo: Span) -> P<Expr> {
3852 let span = lo.to(self.prev_token.span);
3853 let await_expr = self.mk_expr(span, ExprKind::Await(self_arg, self.prev_token.span));
3854 self.recover_from_await_method_call();
3855 await_expr
3856 }
3857
3858 pub(crate) fn mk_expr_with_attrs(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> {
3859 P(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None })
3860 }
3861
3862 pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> P<Expr> {
3863 self.mk_expr_with_attrs(span, kind, AttrVec::new())
3864 }
3865
3866 pub(super) fn mk_expr_err(&self, span: Span, guar: ErrorGuaranteed) -> P<Expr> {
3867 self.mk_expr(span, ExprKind::Err(guar))
3868 }
3869
3870 fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) -> Span {
3873 lhs.attrs
3874 .iter()
3875 .find(|a| a.style == AttrStyle::Outer)
3876 .map_or(lhs_span, |a| a.span)
3877 .to(rhs_span)
3878 }
3879
3880 fn collect_tokens_for_expr(
3881 &mut self,
3882 attrs: AttrWrapper,
3883 f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, P<Expr>>,
3884 ) -> PResult<'a, P<Expr>> {
3885 self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
3886 let res = f(this, attrs)?;
3887 let trailing = Trailing::from(
3888 this.restrictions.contains(Restrictions::STMT_EXPR)
3889 && this.token == token::Semi
3890 || this.token == token::Comma,
3894 );
3895 Ok((res, trailing, UsePreAttrPos::No))
3896 })
3897 }
3898}
3899
3900pub(crate) fn could_be_unclosed_char_literal(ident: Ident) -> bool {
3903 ident.name.as_str().starts_with('\'')
3904 && unescape_char(ident.without_first_quote().name.as_str()).is_ok()
3905}
3906
3907#[derive(Clone, Copy, Subdiagnostic)]
3909pub(crate) enum ForbiddenLetReason {
3910 OtherForbidden,
3912 #[note(parse_not_supported_or)]
3914 NotSupportedOr(#[primary_span] Span),
3915 #[note(parse_not_supported_parentheses)]
3920 NotSupportedParentheses(#[primary_span] Span),
3921}
3922
3923struct CondChecker<'a> {
3933 parser: &'a Parser<'a>,
3934 forbid_let_reason: Option<ForbiddenLetReason>,
3935 missing_let: Option<errors::MaybeMissingLet>,
3936 comparison: Option<errors::MaybeComparison>,
3937}
3938
3939impl<'a> CondChecker<'a> {
3940 fn new(parser: &'a Parser<'a>) -> Self {
3941 CondChecker { parser, forbid_let_reason: None, missing_let: None, comparison: None }
3942 }
3943}
3944
3945impl MutVisitor for CondChecker<'_> {
3946 fn visit_expr(&mut self, e: &mut P<Expr>) {
3947 use ForbiddenLetReason::*;
3948
3949 let span = e.span;
3950 match e.kind {
3951 ExprKind::Let(_, _, _, ref mut recovered @ Recovered::No) => {
3952 if let Some(reason) = self.forbid_let_reason {
3953 *recovered = Recovered::Yes(self.parser.dcx().emit_err(
3954 errors::ExpectedExpressionFoundLet {
3955 span,
3956 reason,
3957 missing_let: self.missing_let,
3958 comparison: self.comparison,
3959 },
3960 ));
3961 } else {
3962 self.parser.psess.gated_spans.gate(sym::let_chains, span);
3963 }
3964 }
3965 ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, _, _) => {
3966 mut_visit::walk_expr(self, e);
3967 }
3968 ExprKind::Binary(Spanned { node: BinOpKind::Or, span: or_span }, _, _)
3969 if let None | Some(NotSupportedOr(_)) = self.forbid_let_reason =>
3970 {
3971 let forbid_let_reason = self.forbid_let_reason;
3972 self.forbid_let_reason = Some(NotSupportedOr(or_span));
3973 mut_visit::walk_expr(self, e);
3974 self.forbid_let_reason = forbid_let_reason;
3975 }
3976 ExprKind::Paren(ref inner)
3977 if let None | Some(NotSupportedParentheses(_)) = self.forbid_let_reason =>
3978 {
3979 let forbid_let_reason = self.forbid_let_reason;
3980 self.forbid_let_reason = Some(NotSupportedParentheses(inner.span));
3981 mut_visit::walk_expr(self, e);
3982 self.forbid_let_reason = forbid_let_reason;
3983 }
3984 ExprKind::Assign(ref lhs, _, span) => {
3985 let forbid_let_reason = self.forbid_let_reason;
3986 self.forbid_let_reason = Some(OtherForbidden);
3987 let missing_let = self.missing_let;
3988 if let ExprKind::Binary(_, _, rhs) = &lhs.kind
3989 && let ExprKind::Path(_, _)
3990 | ExprKind::Struct(_)
3991 | ExprKind::Call(_, _)
3992 | ExprKind::Array(_) = rhs.kind
3993 {
3994 self.missing_let =
3995 Some(errors::MaybeMissingLet { span: rhs.span.shrink_to_lo() });
3996 }
3997 let comparison = self.comparison;
3998 self.comparison = Some(errors::MaybeComparison { span: span.shrink_to_hi() });
3999 mut_visit::walk_expr(self, e);
4000 self.forbid_let_reason = forbid_let_reason;
4001 self.missing_let = missing_let;
4002 self.comparison = comparison;
4003 }
4004 ExprKind::Unary(_, _)
4005 | ExprKind::Await(_, _)
4006 | ExprKind::AssignOp(_, _, _)
4007 | ExprKind::Range(_, _, _)
4008 | ExprKind::Try(_)
4009 | ExprKind::AddrOf(_, _, _)
4010 | ExprKind::Binary(_, _, _)
4011 | ExprKind::Field(_, _)
4012 | ExprKind::Index(_, _, _)
4013 | ExprKind::Call(_, _)
4014 | ExprKind::MethodCall(_)
4015 | ExprKind::Tup(_)
4016 | ExprKind::Paren(_) => {
4017 let forbid_let_reason = self.forbid_let_reason;
4018 self.forbid_let_reason = Some(OtherForbidden);
4019 mut_visit::walk_expr(self, e);
4020 self.forbid_let_reason = forbid_let_reason;
4021 }
4022 ExprKind::Cast(ref mut op, _)
4023 | ExprKind::Type(ref mut op, _)
4024 | ExprKind::UnsafeBinderCast(_, ref mut op, _) => {
4025 let forbid_let_reason = self.forbid_let_reason;
4026 self.forbid_let_reason = Some(OtherForbidden);
4027 self.visit_expr(op);
4028 self.forbid_let_reason = forbid_let_reason;
4029 }
4030 ExprKind::Let(_, _, _, Recovered::Yes(_))
4031 | ExprKind::Array(_)
4032 | ExprKind::ConstBlock(_)
4033 | ExprKind::Lit(_)
4034 | ExprKind::If(_, _, _)
4035 | ExprKind::While(_, _, _)
4036 | ExprKind::ForLoop { .. }
4037 | ExprKind::Loop(_, _, _)
4038 | ExprKind::Match(_, _, _)
4039 | ExprKind::Closure(_)
4040 | ExprKind::Block(_, _)
4041 | ExprKind::Gen(_, _, _, _)
4042 | ExprKind::TryBlock(_)
4043 | ExprKind::Underscore
4044 | ExprKind::Path(_, _)
4045 | ExprKind::Break(_, _)
4046 | ExprKind::Continue(_)
4047 | ExprKind::Ret(_)
4048 | ExprKind::InlineAsm(_)
4049 | ExprKind::OffsetOf(_, _)
4050 | ExprKind::MacCall(_)
4051 | ExprKind::Struct(_)
4052 | ExprKind::Repeat(_, _)
4053 | ExprKind::Yield(_)
4054 | ExprKind::Yeet(_)
4055 | ExprKind::Become(_)
4056 | ExprKind::IncludedBytes(_)
4057 | ExprKind::FormatArgs(_)
4058 | ExprKind::Err(_)
4059 | ExprKind::Dummy => {
4060 }
4062 }
4063 }
4064}