1 use super::diagnostics::SnapshotParser; 2 use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma}; 3 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; 4 use super::{ 5 AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, 6 SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken, 7 }; 8 9 use crate::errors; 10 use crate::maybe_recover_from_interpolated_ty_qpath; 11 use ast::{Path, PathSegment}; 12 use core::mem; 13 use rustc_ast::ptr::P; 14 use rustc_ast::token::{self, Delimiter, Token, TokenKind}; 15 use rustc_ast::tokenstream::Spacing; 16 use rustc_ast::util::case::Case; 17 use rustc_ast::util::classify; 18 use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity}; 19 use rustc_ast::visit::Visitor; 20 use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, UnOp, DUMMY_NODE_ID}; 21 use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind}; 22 use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; 23 use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind}; 24 use rustc_ast_pretty::pprust; 25 use rustc_errors::{ 26 AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, 27 PResult, StashKey, 28 }; 29 use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded}; 30 use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; 31 use rustc_session::lint::BuiltinLintDiagnostics; 32 use rustc_span::source_map::{self, Span, Spanned}; 33 use rustc_span::symbol::kw::PathRoot; 34 use rustc_span::symbol::{kw, sym, Ident, Symbol}; 35 use rustc_span::{BytePos, Pos}; 36 use thin_vec::{thin_vec, ThinVec}; 37 38 /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression 39 /// dropped into the token stream, which happens while parsing the result of 40 /// macro expansion). Placement of these is not as complex as I feared it would 41 /// be. The important thing is to make sure that lookahead doesn't balk at 42 /// `token::Interpolated` tokens. 43 macro_rules! maybe_whole_expr { 44 ($p:expr) => { 45 if let token::Interpolated(nt) = &$p.token.kind { 46 match &**nt { 47 token::NtExpr(e) | token::NtLiteral(e) => { 48 let e = e.clone(); 49 $p.bump(); 50 return Ok(e); 51 } 52 token::NtPath(path) => { 53 let path = (**path).clone(); 54 $p.bump(); 55 return Ok($p.mk_expr($p.prev_token.span, ExprKind::Path(None, path))); 56 } 57 token::NtBlock(block) => { 58 let block = block.clone(); 59 $p.bump(); 60 return Ok($p.mk_expr($p.prev_token.span, ExprKind::Block(block, None))); 61 } 62 _ => {} 63 }; 64 } 65 }; 66 } 67 68 #[derive(Debug)] 69 pub(super) enum LhsExpr { 70 NotYetParsed, 71 AttributesParsed(AttrWrapper), 72 AlreadyParsed { expr: P<Expr>, starts_statement: bool }, 73 } 74 75 impl From<Option<AttrWrapper>> for LhsExpr { 76 /// Converts `Some(attrs)` into `LhsExpr::AttributesParsed(attrs)` 77 /// and `None` into `LhsExpr::NotYetParsed`. 78 /// 79 /// This conversion does not allocate. from(o: Option<AttrWrapper>) -> Self80 fn from(o: Option<AttrWrapper>) -> Self { 81 if let Some(attrs) = o { LhsExpr::AttributesParsed(attrs) } else { LhsExpr::NotYetParsed } 82 } 83 } 84 85 impl From<P<Expr>> for LhsExpr { 86 /// Converts the `expr: P<Expr>` into `LhsExpr::AlreadyParsed { expr, starts_statement: false }`. 87 /// 88 /// This conversion does not allocate. from(expr: P<Expr>) -> Self89 fn from(expr: P<Expr>) -> Self { 90 LhsExpr::AlreadyParsed { expr, starts_statement: false } 91 } 92 } 93 94 #[derive(Debug)] 95 enum DestructuredFloat { 96 /// 1e2 97 Single(Symbol, Span), 98 /// 1. 99 TrailingDot(Symbol, Span, Span), 100 /// 1.2 | 1.2e3 101 MiddleDot(Symbol, Span, Span, Symbol, Span), 102 /// Invalid 103 Error, 104 } 105 106 impl<'a> Parser<'a> { 107 /// Parses an expression. 108 #[inline] parse_expr(&mut self) -> PResult<'a, P<Expr>>109 pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> { 110 self.current_closure.take(); 111 112 self.parse_expr_res(Restrictions::empty(), None) 113 } 114 115 /// Parses an expression, forcing tokens to be collected parse_expr_force_collect(&mut self) -> PResult<'a, P<Expr>>116 pub fn parse_expr_force_collect(&mut self) -> PResult<'a, P<Expr>> { 117 self.collect_tokens_no_attrs(|this| this.parse_expr()) 118 } 119 parse_expr_anon_const(&mut self) -> PResult<'a, AnonConst>120 pub fn parse_expr_anon_const(&mut self) -> PResult<'a, AnonConst> { 121 self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value }) 122 } 123 parse_expr_catch_underscore(&mut self) -> PResult<'a, P<Expr>>124 fn parse_expr_catch_underscore(&mut self) -> PResult<'a, P<Expr>> { 125 match self.parse_expr() { 126 Ok(expr) => Ok(expr), 127 Err(mut err) => match self.token.ident() { 128 Some((Ident { name: kw::Underscore, .. }, false)) 129 if self.may_recover() && self.look_ahead(1, |t| t == &token::Comma) => 130 { 131 // Special-case handling of `foo(_, _, _)` 132 err.emit(); 133 self.bump(); 134 Ok(self.mk_expr(self.prev_token.span, ExprKind::Err)) 135 } 136 _ => Err(err), 137 }, 138 } 139 } 140 141 /// Parses a sequence of expressions delimited by parentheses. parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<P<Expr>>>142 fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<P<Expr>>> { 143 self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore()).map(|(r, _)| r) 144 } 145 146 /// Parses an expression, subject to the given restrictions. 147 #[inline] parse_expr_res( &mut self, r: Restrictions, already_parsed_attrs: Option<AttrWrapper>, ) -> PResult<'a, P<Expr>>148 pub(super) fn parse_expr_res( 149 &mut self, 150 r: Restrictions, 151 already_parsed_attrs: Option<AttrWrapper>, 152 ) -> PResult<'a, P<Expr>> { 153 self.with_res(r, |this| this.parse_expr_assoc(already_parsed_attrs)) 154 } 155 156 /// Parses an associative expression. 157 /// 158 /// This parses an expression accounting for associativity and precedence of the operators in 159 /// the expression. 160 #[inline] parse_expr_assoc( &mut self, already_parsed_attrs: Option<AttrWrapper>, ) -> PResult<'a, P<Expr>>161 fn parse_expr_assoc( 162 &mut self, 163 already_parsed_attrs: Option<AttrWrapper>, 164 ) -> PResult<'a, P<Expr>> { 165 self.parse_expr_assoc_with(0, already_parsed_attrs.into()) 166 } 167 168 /// Parses an associative expression with operators of at least `min_prec` precedence. parse_expr_assoc_with( &mut self, min_prec: usize, lhs: LhsExpr, ) -> PResult<'a, P<Expr>>169 pub(super) fn parse_expr_assoc_with( 170 &mut self, 171 min_prec: usize, 172 lhs: LhsExpr, 173 ) -> PResult<'a, P<Expr>> { 174 let mut starts_stmt = false; 175 let mut lhs = if let LhsExpr::AlreadyParsed { expr, starts_statement } = lhs { 176 starts_stmt = starts_statement; 177 expr 178 } else { 179 let attrs = match lhs { 180 LhsExpr::AttributesParsed(attrs) => Some(attrs), 181 _ => None, 182 }; 183 if self.token.is_range_separator() { 184 return self.parse_expr_prefix_range(attrs); 185 } else { 186 self.parse_expr_prefix(attrs)? 187 } 188 }; 189 190 if !self.should_continue_as_assoc_expr(&lhs) { 191 return Ok(lhs); 192 } 193 194 self.expected_tokens.push(TokenType::Operator); 195 while let Some(op) = self.check_assoc_op() { 196 // Adjust the span for interpolated LHS to point to the `$lhs` token 197 // and not to what it refers to. 198 let lhs_span = match self.prev_token.kind { 199 TokenKind::Interpolated(..) => self.prev_token.span, 200 _ => lhs.span, 201 }; 202 203 let cur_op_span = self.token.span; 204 let restrictions = if op.node.is_assign_like() { 205 self.restrictions & Restrictions::NO_STRUCT_LITERAL 206 } else { 207 self.restrictions 208 }; 209 let prec = op.node.precedence(); 210 if prec < min_prec { 211 break; 212 } 213 // Check for deprecated `...` syntax 214 if self.token == token::DotDotDot && op.node == AssocOp::DotDotEq { 215 self.err_dotdotdot_syntax(self.token.span); 216 } 217 218 if self.token == token::LArrow { 219 self.err_larrow_operator(self.token.span); 220 } 221 222 self.bump(); 223 if op.node.is_comparison() { 224 if let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? { 225 return Ok(expr); 226 } 227 } 228 229 // Look for JS' `===` and `!==` and recover 230 if (op.node == AssocOp::Equal || op.node == AssocOp::NotEqual) 231 && self.token.kind == token::Eq 232 && self.prev_token.span.hi() == self.token.span.lo() 233 { 234 let sp = op.span.to(self.token.span); 235 let sugg = match op.node { 236 AssocOp::Equal => "==", 237 AssocOp::NotEqual => "!=", 238 _ => unreachable!(), 239 } 240 .into(); 241 let invalid = format!("{}=", &sugg); 242 self.sess.emit_err(errors::InvalidComparisonOperator { 243 span: sp, 244 invalid: invalid.clone(), 245 sub: errors::InvalidComparisonOperatorSub::Correctable { 246 span: sp, 247 invalid, 248 correct: sugg, 249 }, 250 }); 251 self.bump(); 252 } 253 254 // Look for PHP's `<>` and recover 255 if op.node == AssocOp::Less 256 && self.token.kind == token::Gt 257 && self.prev_token.span.hi() == self.token.span.lo() 258 { 259 let sp = op.span.to(self.token.span); 260 self.sess.emit_err(errors::InvalidComparisonOperator { 261 span: sp, 262 invalid: "<>".into(), 263 sub: errors::InvalidComparisonOperatorSub::Correctable { 264 span: sp, 265 invalid: "<>".into(), 266 correct: "!=".into(), 267 }, 268 }); 269 self.bump(); 270 } 271 272 // Look for C++'s `<=>` and recover 273 if op.node == AssocOp::LessEqual 274 && self.token.kind == token::Gt 275 && self.prev_token.span.hi() == self.token.span.lo() 276 { 277 let sp = op.span.to(self.token.span); 278 self.sess.emit_err(errors::InvalidComparisonOperator { 279 span: sp, 280 invalid: "<=>".into(), 281 sub: errors::InvalidComparisonOperatorSub::Spaceship(sp), 282 }); 283 self.bump(); 284 } 285 286 if self.prev_token == token::BinOp(token::Plus) 287 && self.token == token::BinOp(token::Plus) 288 && self.prev_token.span.between(self.token.span).is_empty() 289 { 290 let op_span = self.prev_token.span.to(self.token.span); 291 // Eat the second `+` 292 self.bump(); 293 lhs = self.recover_from_postfix_increment(lhs, op_span, starts_stmt)?; 294 continue; 295 } 296 297 if self.prev_token == token::BinOp(token::Minus) 298 && self.token == token::BinOp(token::Minus) 299 && self.prev_token.span.between(self.token.span).is_empty() 300 && !self.look_ahead(1, |tok| tok.can_begin_expr()) 301 { 302 let op_span = self.prev_token.span.to(self.token.span); 303 // Eat the second `-` 304 self.bump(); 305 lhs = self.recover_from_postfix_decrement(lhs, op_span, starts_stmt)?; 306 continue; 307 } 308 309 let op = op.node; 310 // Special cases: 311 if op == AssocOp::As { 312 lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?; 313 continue; 314 } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq { 315 // If we didn't have to handle `x..`/`x..=`, it would be pretty easy to 316 // generalise it to the Fixity::None code. 317 lhs = self.parse_expr_range(prec, lhs, op, cur_op_span)?; 318 break; 319 } 320 321 let fixity = op.fixity(); 322 let prec_adjustment = match fixity { 323 Fixity::Right => 0, 324 Fixity::Left => 1, 325 // We currently have no non-associative operators that are not handled above by 326 // the special cases. The code is here only for future convenience. 327 Fixity::None => 1, 328 }; 329 let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| { 330 this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::NotYetParsed) 331 })?; 332 333 let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span); 334 lhs = match op { 335 AssocOp::Add 336 | AssocOp::Subtract 337 | AssocOp::Multiply 338 | AssocOp::Divide 339 | AssocOp::Modulus 340 | AssocOp::LAnd 341 | AssocOp::LOr 342 | AssocOp::BitXor 343 | AssocOp::BitAnd 344 | AssocOp::BitOr 345 | AssocOp::ShiftLeft 346 | AssocOp::ShiftRight 347 | AssocOp::Equal 348 | AssocOp::Less 349 | AssocOp::LessEqual 350 | AssocOp::NotEqual 351 | AssocOp::Greater 352 | AssocOp::GreaterEqual => { 353 let ast_op = op.to_ast_binop().unwrap(); 354 let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs); 355 self.mk_expr(span, binary) 356 } 357 AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs, cur_op_span)), 358 AssocOp::AssignOp(k) => { 359 let aop = match k { 360 token::Plus => BinOpKind::Add, 361 token::Minus => BinOpKind::Sub, 362 token::Star => BinOpKind::Mul, 363 token::Slash => BinOpKind::Div, 364 token::Percent => BinOpKind::Rem, 365 token::Caret => BinOpKind::BitXor, 366 token::And => BinOpKind::BitAnd, 367 token::Or => BinOpKind::BitOr, 368 token::Shl => BinOpKind::Shl, 369 token::Shr => BinOpKind::Shr, 370 }; 371 let aopexpr = self.mk_assign_op(source_map::respan(cur_op_span, aop), lhs, rhs); 372 self.mk_expr(span, aopexpr) 373 } 374 AssocOp::As | AssocOp::DotDot | AssocOp::DotDotEq => { 375 self.span_bug(span, "AssocOp should have been handled by special case") 376 } 377 }; 378 379 if let Fixity::None = fixity { 380 break; 381 } 382 } 383 384 Ok(lhs) 385 } 386 should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool387 fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool { 388 match (self.expr_is_complete(lhs), AssocOp::from_token(&self.token)) { 389 // Semi-statement forms are odd: 390 // See https://github.com/rust-lang/rust/issues/29071 391 (true, None) => false, 392 (false, _) => true, // Continue parsing the expression. 393 // An exhaustive check is done in the following block, but these are checked first 394 // because they *are* ambiguous but also reasonable looking incorrect syntax, so we 395 // want to keep their span info to improve diagnostics in these cases in a later stage. 396 (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3` 397 (true, Some(AssocOp::Subtract)) | // `{ 42 } -5` 398 (true, Some(AssocOp::Add)) | // `{ 42 } + 42` (unary plus) 399 (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }` 400 (true, Some(AssocOp::LOr)) | // `{ 42 } || 42` ("logical or" or closure) 401 (true, Some(AssocOp::BitOr)) // `{ 42 } | 42` or `{ 42 } |x| 42` 402 => { 403 // These cases are ambiguous and can't be identified in the parser alone. 404 // 405 // Bitwise AND is left out because guessing intent is hard. We can make 406 // suggestions based on the assumption that double-refs are rarely intentional, 407 // and closures are distinct enough that they don't get mixed up with their 408 // return value. 409 let sp = self.sess.source_map().start_point(self.token.span); 410 self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); 411 false 412 } 413 (true, Some(op)) if !op.can_continue_expr_unambiguously() => false, 414 (true, Some(_)) => { 415 self.error_found_expr_would_be_stmt(lhs); 416 true 417 } 418 } 419 } 420 421 /// We've found an expression that would be parsed as a statement, 422 /// but the next token implies this should be parsed as an expression. 423 /// For example: `if let Some(x) = x { x } else { 0 } / 2`. error_found_expr_would_be_stmt(&self, lhs: &Expr)424 fn error_found_expr_would_be_stmt(&self, lhs: &Expr) { 425 self.sess.emit_err(errors::FoundExprWouldBeStmt { 426 span: self.token.span, 427 token: self.token.clone(), 428 suggestion: ExprParenthesesNeeded::surrounding(lhs.span), 429 }); 430 } 431 432 /// Possibly translate the current token to an associative operator. 433 /// The method does not advance the current token. 434 /// 435 /// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively. check_assoc_op(&self) -> Option<Spanned<AssocOp>>436 fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> { 437 let (op, span) = match (AssocOp::from_token(&self.token), self.token.ident()) { 438 // When parsing const expressions, stop parsing when encountering `>`. 439 ( 440 Some( 441 AssocOp::ShiftRight 442 | AssocOp::Greater 443 | AssocOp::GreaterEqual 444 | AssocOp::AssignOp(token::BinOpToken::Shr), 445 ), 446 _, 447 ) if self.restrictions.contains(Restrictions::CONST_EXPR) => { 448 return None; 449 } 450 (Some(op), _) => (op, self.token.span), 451 (None, Some((Ident { name: sym::and, span }, false))) if self.may_recover() => { 452 self.sess.emit_err(errors::InvalidLogicalOperator { 453 span: self.token.span, 454 incorrect: "and".into(), 455 sub: errors::InvalidLogicalOperatorSub::Conjunction(self.token.span), 456 }); 457 (AssocOp::LAnd, span) 458 } 459 (None, Some((Ident { name: sym::or, span }, false))) if self.may_recover() => { 460 self.sess.emit_err(errors::InvalidLogicalOperator { 461 span: self.token.span, 462 incorrect: "or".into(), 463 sub: errors::InvalidLogicalOperatorSub::Disjunction(self.token.span), 464 }); 465 (AssocOp::LOr, span) 466 } 467 _ => return None, 468 }; 469 Some(source_map::respan(span, op)) 470 } 471 472 /// Checks if this expression is a successfully parsed statement. expr_is_complete(&self, e: &Expr) -> bool473 fn expr_is_complete(&self, e: &Expr) -> bool { 474 self.restrictions.contains(Restrictions::STMT_EXPR) 475 && !classify::expr_requires_semi_to_be_stmt(e) 476 } 477 478 /// Parses `x..y`, `x..=y`, and `x..`/`x..=`. 479 /// The other two variants are handled in `parse_prefix_range_expr` below. parse_expr_range( &mut self, prec: usize, lhs: P<Expr>, op: AssocOp, cur_op_span: Span, ) -> PResult<'a, P<Expr>>480 fn parse_expr_range( 481 &mut self, 482 prec: usize, 483 lhs: P<Expr>, 484 op: AssocOp, 485 cur_op_span: Span, 486 ) -> PResult<'a, P<Expr>> { 487 let rhs = if self.is_at_start_of_range_notation_rhs() { 488 Some(self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)?) 489 } else { 490 None 491 }; 492 let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span); 493 let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span); 494 let limits = 495 if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed }; 496 let range = self.mk_range(Some(lhs), rhs, limits); 497 Ok(self.mk_expr(span, range)) 498 } 499 is_at_start_of_range_notation_rhs(&self) -> bool500 fn is_at_start_of_range_notation_rhs(&self) -> bool { 501 if self.token.can_begin_expr() { 502 // Parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`. 503 if self.token == token::OpenDelim(Delimiter::Brace) { 504 return !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL); 505 } 506 true 507 } else { 508 false 509 } 510 } 511 512 /// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`. parse_expr_prefix_range(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>>513 fn parse_expr_prefix_range(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> { 514 // Check for deprecated `...` syntax. 515 if self.token == token::DotDotDot { 516 self.err_dotdotdot_syntax(self.token.span); 517 } 518 519 debug_assert!( 520 self.token.is_range_separator(), 521 "parse_prefix_range_expr: token {:?} is not DotDot/DotDotEq", 522 self.token 523 ); 524 525 let limits = match self.token.kind { 526 token::DotDot => RangeLimits::HalfOpen, 527 _ => RangeLimits::Closed, 528 }; 529 let op = AssocOp::from_token(&self.token); 530 // FIXME: `parse_prefix_range_expr` is called when the current 531 // token is `DotDot`, `DotDotDot`, or `DotDotEq`. If we haven't already 532 // parsed attributes, then trying to parse them here will always fail. 533 // We should figure out how we want attributes on range expressions to work. 534 let attrs = self.parse_or_use_outer_attributes(attrs)?; 535 self.collect_tokens_for_expr(attrs, |this, attrs| { 536 let lo = this.token.span; 537 this.bump(); 538 let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() { 539 // RHS must be parsed with more associativity than the dots. 540 this.parse_expr_assoc_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed) 541 .map(|x| (lo.to(x.span), Some(x)))? 542 } else { 543 (lo, None) 544 }; 545 let range = this.mk_range(None, opt_end, limits); 546 Ok(this.mk_expr_with_attrs(span, range, attrs)) 547 }) 548 } 549 550 /// Parses a prefix-unary-operator expr. parse_expr_prefix(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>>551 fn parse_expr_prefix(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> { 552 let attrs = self.parse_or_use_outer_attributes(attrs)?; 553 let lo = self.token.span; 554 555 macro_rules! make_it { 556 ($this:ident, $attrs:expr, |this, _| $body:expr) => { 557 $this.collect_tokens_for_expr($attrs, |$this, attrs| { 558 let (hi, ex) = $body?; 559 Ok($this.mk_expr_with_attrs(lo.to(hi), ex, attrs)) 560 }) 561 }; 562 } 563 564 let this = self; 565 566 // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr() 567 match this.token.uninterpolate().kind { 568 // `!expr` 569 token::Not => make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Not)), 570 // `~expr` 571 token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)), 572 // `-expr` 573 token::BinOp(token::Minus) => { 574 make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Neg)) 575 } 576 // `*expr` 577 token::BinOp(token::Star) => { 578 make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Deref)) 579 } 580 // `&expr` and `&&expr` 581 token::BinOp(token::And) | token::AndAnd => { 582 make_it!(this, attrs, |this, _| this.parse_expr_borrow(lo)) 583 } 584 // `+lit` 585 token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => { 586 let mut err = errors::LeadingPlusNotSupported { 587 span: lo, 588 remove_plus: None, 589 add_parentheses: None, 590 }; 591 592 // a block on the LHS might have been intended to be an expression instead 593 if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) { 594 err.add_parentheses = Some(ExprParenthesesNeeded::surrounding(*sp)); 595 } else { 596 err.remove_plus = Some(lo); 597 } 598 this.sess.emit_err(err); 599 600 this.bump(); 601 this.parse_expr_prefix(None) 602 } 603 // Recover from `++x`: 604 token::BinOp(token::Plus) 605 if this.look_ahead(1, |t| *t == token::BinOp(token::Plus)) => 606 { 607 let starts_stmt = this.prev_token == token::Semi 608 || this.prev_token == token::CloseDelim(Delimiter::Brace); 609 let pre_span = this.token.span.to(this.look_ahead(1, |t| t.span)); 610 // Eat both `+`s. 611 this.bump(); 612 this.bump(); 613 614 let operand_expr = this.parse_expr_dot_or_call(Default::default())?; 615 this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt) 616 } 617 token::Ident(..) if this.token.is_keyword(kw::Box) => { 618 make_it!(this, attrs, |this, _| this.parse_expr_box(lo)) 619 } 620 token::Ident(..) if this.may_recover() && this.is_mistaken_not_ident_negation() => { 621 make_it!(this, attrs, |this, _| this.recover_not_expr(lo)) 622 } 623 _ => return this.parse_expr_dot_or_call(Some(attrs)), 624 } 625 } 626 parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)>627 fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> { 628 self.bump(); 629 let expr = self.parse_expr_prefix(None); 630 let (span, expr) = self.interpolated_or_expr_span(expr)?; 631 Ok((lo.to(span), expr)) 632 } 633 parse_expr_unary(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)>634 fn parse_expr_unary(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> { 635 let (span, expr) = self.parse_expr_prefix_common(lo)?; 636 Ok((span, self.mk_unary(op, expr))) 637 } 638 639 /// Recover on `~expr` in favor of `!expr`. recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)>640 fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { 641 self.sess.emit_err(errors::TildeAsUnaryOperator(lo)); 642 643 self.parse_expr_unary(lo, UnOp::Not) 644 } 645 646 /// Parse `box expr` - this syntax has been removed, but we still parse this 647 /// for now to provide an automated way to fix usages of it parse_expr_box(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)>648 fn parse_expr_box(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { 649 let (span, expr) = self.parse_expr_prefix_common(lo)?; 650 let code = self.sess.source_map().span_to_snippet(span.with_lo(lo.hi())).unwrap(); 651 self.sess.emit_err(errors::BoxSyntaxRemoved { span, code: code.trim() }); 652 // So typechecking works, parse `box <expr>` as `::std::boxed::Box::new(expr)` 653 let path = Path { 654 span, 655 segments: [ 656 PathSegment::from_ident(Ident::with_dummy_span(PathRoot)), 657 PathSegment::from_ident(Ident::with_dummy_span(sym::std)), 658 PathSegment::from_ident(Ident::from_str("boxed")), 659 PathSegment::from_ident(Ident::from_str("Box")), 660 PathSegment::from_ident(Ident::with_dummy_span(sym::new)), 661 ] 662 .into(), 663 tokens: None, 664 }; 665 let path = self.mk_expr(span, ExprKind::Path(None, path)); 666 Ok((span, self.mk_call(path, ThinVec::from([expr])))) 667 } 668 is_mistaken_not_ident_negation(&self) -> bool669 fn is_mistaken_not_ident_negation(&self) -> bool { 670 let token_cannot_continue_expr = |t: &Token| match t.uninterpolate().kind { 671 // These tokens can start an expression after `!`, but 672 // can't continue an expression after an ident 673 token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw), 674 token::Literal(..) | token::Pound => true, 675 _ => t.is_whole_expr(), 676 }; 677 self.token.is_ident_named(sym::not) && self.look_ahead(1, token_cannot_continue_expr) 678 } 679 680 /// Recover on `not expr` in favor of `!expr`. recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)>681 fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { 682 let negated_token = self.look_ahead(1, |t| t.clone()); 683 684 let sub_diag = if negated_token.is_numeric_lit() { 685 errors::NotAsNegationOperatorSub::SuggestNotBitwise 686 } else if negated_token.is_bool_lit() { 687 errors::NotAsNegationOperatorSub::SuggestNotLogical 688 } else { 689 errors::NotAsNegationOperatorSub::SuggestNotDefault 690 }; 691 692 self.sess.emit_err(errors::NotAsNegationOperator { 693 negated: negated_token.span, 694 negated_desc: super::token_descr(&negated_token), 695 // Span the `not` plus trailing whitespace to avoid 696 // trailing whitespace after the `!` in our suggestion 697 sub: sub_diag( 698 self.sess.source_map().span_until_non_whitespace(lo.to(negated_token.span)), 699 ), 700 }); 701 702 self.parse_expr_unary(lo, UnOp::Not) 703 } 704 705 /// Returns the span of expr, if it was not interpolated or the span of the interpolated token. interpolated_or_expr_span( &self, expr: PResult<'a, P<Expr>>, ) -> PResult<'a, (Span, P<Expr>)>706 fn interpolated_or_expr_span( 707 &self, 708 expr: PResult<'a, P<Expr>>, 709 ) -> PResult<'a, (Span, P<Expr>)> { 710 expr.map(|e| { 711 ( 712 match self.prev_token.kind { 713 TokenKind::Interpolated(..) => self.prev_token.span, 714 _ => e.span, 715 }, 716 e, 717 ) 718 }) 719 } 720 parse_assoc_op_cast( &mut self, lhs: P<Expr>, lhs_span: Span, expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind, ) -> PResult<'a, P<Expr>>721 fn parse_assoc_op_cast( 722 &mut self, 723 lhs: P<Expr>, 724 lhs_span: Span, 725 expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind, 726 ) -> PResult<'a, P<Expr>> { 727 let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| { 728 this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, rhs.span), expr_kind(lhs, rhs)) 729 }; 730 731 // Save the state of the parser before parsing type normally, in case there is a 732 // LessThan comparison after this cast. 733 let parser_snapshot_before_type = self.clone(); 734 let cast_expr = match self.parse_as_cast_ty() { 735 Ok(rhs) => mk_expr(self, lhs, rhs), 736 Err(type_err) => { 737 if !self.may_recover() { 738 return Err(type_err); 739 } 740 741 // Rewind to before attempting to parse the type with generics, to recover 742 // from situations like `x as usize < y` in which we first tried to parse 743 // `usize < y` as a type with generic arguments. 744 let parser_snapshot_after_type = mem::replace(self, parser_snapshot_before_type); 745 746 // Check for typo of `'a: loop { break 'a }` with a missing `'`. 747 match (&lhs.kind, &self.token.kind) { 748 ( 749 // `foo: ` 750 ExprKind::Path(None, ast::Path { segments, .. }), 751 token::Ident(kw::For | kw::Loop | kw::While, false), 752 ) if segments.len() == 1 => { 753 let snapshot = self.create_snapshot_for_diagnostic(); 754 let label = Label { 755 ident: Ident::from_str_and_span( 756 &format!("'{}", segments[0].ident), 757 segments[0].ident.span, 758 ), 759 }; 760 match self.parse_expr_labeled(label, false) { 761 Ok(expr) => { 762 type_err.cancel(); 763 self.sess.emit_err(errors::MalformedLoopLabel { 764 span: label.ident.span, 765 correct_label: label.ident, 766 }); 767 return Ok(expr); 768 } 769 Err(err) => { 770 err.cancel(); 771 self.restore_snapshot(snapshot); 772 } 773 } 774 } 775 _ => {} 776 } 777 778 match self.parse_path(PathStyle::Expr) { 779 Ok(path) => { 780 let span_after_type = parser_snapshot_after_type.token.span; 781 let expr = mk_expr( 782 self, 783 lhs, 784 self.mk_ty(path.span, TyKind::Path(None, path.clone())), 785 ); 786 787 let args_span = self.look_ahead(1, |t| t.span).to(span_after_type); 788 let suggestion = errors::ComparisonOrShiftInterpretedAsGenericSugg { 789 left: expr.span.shrink_to_lo(), 790 right: expr.span.shrink_to_hi(), 791 }; 792 793 match self.token.kind { 794 token::Lt => { 795 self.sess.emit_err(errors::ComparisonInterpretedAsGeneric { 796 comparison: self.token.span, 797 r#type: path, 798 args: args_span, 799 suggestion, 800 }) 801 } 802 token::BinOp(token::Shl) => { 803 self.sess.emit_err(errors::ShiftInterpretedAsGeneric { 804 shift: self.token.span, 805 r#type: path, 806 args: args_span, 807 suggestion, 808 }) 809 } 810 _ => { 811 // We can end up here even without `<` being the next token, for 812 // example because `parse_ty_no_plus` returns `Err` on keywords, 813 // but `parse_path` returns `Ok` on them due to error recovery. 814 // Return original error and parser state. 815 *self = parser_snapshot_after_type; 816 return Err(type_err); 817 } 818 }; 819 820 // Successfully parsed the type path leaving a `<` yet to parse. 821 type_err.cancel(); 822 823 // Keep `x as usize` as an expression in AST and continue parsing. 824 expr 825 } 826 Err(path_err) => { 827 // Couldn't parse as a path, return original error and parser state. 828 path_err.cancel(); 829 *self = parser_snapshot_after_type; 830 return Err(type_err); 831 } 832 } 833 } 834 }; 835 836 self.parse_and_disallow_postfix_after_cast(cast_expr) 837 } 838 839 /// Parses a postfix operators such as `.`, `?`, or index (`[]`) after a cast, 840 /// then emits an error and returns the newly parsed tree. 841 /// The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`. parse_and_disallow_postfix_after_cast( &mut self, cast_expr: P<Expr>, ) -> PResult<'a, P<Expr>>842 fn parse_and_disallow_postfix_after_cast( 843 &mut self, 844 cast_expr: P<Expr>, 845 ) -> PResult<'a, P<Expr>> { 846 if let ExprKind::Type(_, _) = cast_expr.kind { 847 panic!("ExprKind::Type must not be parsed"); 848 } 849 850 let span = cast_expr.span; 851 852 let with_postfix = self.parse_expr_dot_or_call_with_(cast_expr, span)?; 853 854 // Check if an illegal postfix operator has been added after the cast. 855 // If the resulting expression is not a cast, it is an illegal postfix operator. 856 if !matches!(with_postfix.kind, ExprKind::Cast(_, _)) { 857 let msg = format!( 858 "cast cannot be followed by {}", 859 match with_postfix.kind { 860 ExprKind::Index(_, _) => "indexing", 861 ExprKind::Try(_) => "`?`", 862 ExprKind::Field(_, _) => "a field access", 863 ExprKind::MethodCall(_) => "a method call", 864 ExprKind::Call(_, _) => "a function call", 865 ExprKind::Await(_, _) => "`.await`", 866 ExprKind::Err => return Ok(with_postfix), 867 _ => unreachable!("parse_dot_or_call_expr_with_ shouldn't produce this"), 868 } 869 ); 870 let mut err = self.struct_span_err(span, msg); 871 872 let suggest_parens = |err: &mut Diagnostic| { 873 let suggestions = vec![ 874 (span.shrink_to_lo(), "(".to_string()), 875 (span.shrink_to_hi(), ")".to_string()), 876 ]; 877 err.multipart_suggestion( 878 "try surrounding the expression in parentheses", 879 suggestions, 880 Applicability::MachineApplicable, 881 ); 882 }; 883 884 suggest_parens(&mut err); 885 886 err.emit(); 887 }; 888 Ok(with_postfix) 889 } 890 891 /// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`. parse_expr_borrow(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)>892 fn parse_expr_borrow(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { 893 self.expect_and()?; 894 let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon); 895 let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below. 896 let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo); 897 let expr = if self.token.is_range_separator() { 898 self.parse_expr_prefix_range(None) 899 } else { 900 self.parse_expr_prefix(None) 901 }; 902 let (hi, expr) = self.interpolated_or_expr_span(expr)?; 903 let span = lo.to(hi); 904 if let Some(lt) = lifetime { 905 self.error_remove_borrow_lifetime(span, lt.ident.span); 906 } 907 Ok((span, ExprKind::AddrOf(borrow_kind, mutbl, expr))) 908 } 909 error_remove_borrow_lifetime(&self, span: Span, lt_span: Span)910 fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) { 911 self.sess.emit_err(errors::LifetimeInBorrowExpression { span, lifetime_span: lt_span }); 912 } 913 914 /// Parse `mut?` or `raw [ const | mut ]`. parse_borrow_modifiers(&mut self, lo: Span) -> (ast::BorrowKind, ast::Mutability)915 fn parse_borrow_modifiers(&mut self, lo: Span) -> (ast::BorrowKind, ast::Mutability) { 916 if self.check_keyword(kw::Raw) && self.look_ahead(1, Token::is_mutability) { 917 // `raw [ const | mut ]`. 918 let found_raw = self.eat_keyword(kw::Raw); 919 assert!(found_raw); 920 let mutability = self.parse_const_or_mut().unwrap(); 921 self.sess.gated_spans.gate(sym::raw_ref_op, lo.to(self.prev_token.span)); 922 (ast::BorrowKind::Raw, mutability) 923 } else { 924 // `mut?` 925 (ast::BorrowKind::Ref, self.parse_mutability()) 926 } 927 } 928 929 /// Parses `a.b` or `a(13)` or `a[4]` or just `a`. parse_expr_dot_or_call(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>>930 fn parse_expr_dot_or_call(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> { 931 let attrs = self.parse_or_use_outer_attributes(attrs)?; 932 self.collect_tokens_for_expr(attrs, |this, attrs| { 933 let base = this.parse_expr_bottom(); 934 let (span, base) = this.interpolated_or_expr_span(base)?; 935 this.parse_expr_dot_or_call_with(base, span, attrs) 936 }) 937 } 938 parse_expr_dot_or_call_with( &mut self, e0: P<Expr>, lo: Span, mut attrs: ast::AttrVec, ) -> PResult<'a, P<Expr>>939 pub(super) fn parse_expr_dot_or_call_with( 940 &mut self, 941 e0: P<Expr>, 942 lo: Span, 943 mut attrs: ast::AttrVec, 944 ) -> PResult<'a, P<Expr>> { 945 // Stitch the list of outer attributes onto the return value. 946 // A little bit ugly, but the best way given the current code 947 // structure 948 let res = self.parse_expr_dot_or_call_with_(e0, lo); 949 if attrs.is_empty() { 950 res 951 } else { 952 res.map(|expr| { 953 expr.map(|mut expr| { 954 attrs.extend(expr.attrs); 955 expr.attrs = attrs; 956 expr 957 }) 958 }) 959 } 960 } 961 parse_expr_dot_or_call_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>>962 fn parse_expr_dot_or_call_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> { 963 loop { 964 let has_question = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) { 965 // we are using noexpect here because we don't expect a `?` directly after a `return` 966 // which could be suggested otherwise 967 self.eat_noexpect(&token::Question) 968 } else { 969 self.eat(&token::Question) 970 }; 971 if has_question { 972 // `expr?` 973 e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e)); 974 continue; 975 } 976 let has_dot = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) { 977 // we are using noexpect here because we don't expect a `.` directly after a `return` 978 // which could be suggested otherwise 979 self.eat_noexpect(&token::Dot) 980 } else { 981 self.eat(&token::Dot) 982 }; 983 if has_dot { 984 // expr.f 985 e = self.parse_dot_suffix_expr(lo, e)?; 986 continue; 987 } 988 if self.expr_is_complete(&e) { 989 return Ok(e); 990 } 991 e = match self.token.kind { 992 token::OpenDelim(Delimiter::Parenthesis) => self.parse_expr_fn_call(lo, e), 993 token::OpenDelim(Delimiter::Bracket) => self.parse_expr_index(lo, e)?, 994 _ => return Ok(e), 995 } 996 } 997 } 998 parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>>999 fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> { 1000 match self.token.uninterpolate().kind { 1001 token::Ident(..) => self.parse_dot_suffix(base, lo), 1002 token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => { 1003 Ok(self.parse_expr_tuple_field_access(lo, base, symbol, suffix, None)) 1004 } 1005 token::Literal(token::Lit { kind: token::Float, symbol, suffix }) => { 1006 Ok(self.parse_expr_tuple_field_access_float(lo, base, symbol, suffix)) 1007 } 1008 _ => { 1009 self.error_unexpected_after_dot(); 1010 Ok(base) 1011 } 1012 } 1013 } 1014 error_unexpected_after_dot(&self)1015 fn error_unexpected_after_dot(&self) { 1016 let actual = pprust::token_to_string(&self.token); 1017 let span = self.token.span; 1018 let sm = self.sess.source_map(); 1019 let (span, actual) = match (&self.token.kind, self.subparser_name) { 1020 (token::Eof, Some(_)) if let Ok(actual) = sm.span_to_snippet(sm.next_point(span)) => 1021 (span.shrink_to_hi(), actual.into()), 1022 _ => (span, actual), 1023 }; 1024 self.sess.emit_err(errors::UnexpectedTokenAfterDot { span, actual }); 1025 } 1026 1027 // We need an identifier or integer, but the next token is a float. 1028 // Break the float into components to extract the identifier or integer. 1029 // FIXME: With current `TokenCursor` it's hard to break tokens into more than 2 1030 // parts unless those parts are processed immediately. `TokenCursor` should either 1031 // support pushing "future tokens" (would be also helpful to `break_and_eat`), or 1032 // we should break everything including floats into more basic proc-macro style 1033 // tokens in the lexer (probably preferable). 1034 // See also `TokenKind::break_two_token_op` which does similar splitting of `>>` into `>`. break_up_float(&mut self, float: Symbol) -> DestructuredFloat1035 fn break_up_float(&mut self, float: Symbol) -> DestructuredFloat { 1036 #[derive(Debug)] 1037 enum FloatComponent { 1038 IdentLike(String), 1039 Punct(char), 1040 } 1041 use FloatComponent::*; 1042 1043 let float_str = float.as_str(); 1044 let mut components = Vec::new(); 1045 let mut ident_like = String::new(); 1046 for c in float_str.chars() { 1047 if c == '_' || c.is_ascii_alphanumeric() { 1048 ident_like.push(c); 1049 } else if matches!(c, '.' | '+' | '-') { 1050 if !ident_like.is_empty() { 1051 components.push(IdentLike(mem::take(&mut ident_like))); 1052 } 1053 components.push(Punct(c)); 1054 } else { 1055 panic!("unexpected character in a float token: {:?}", c) 1056 } 1057 } 1058 if !ident_like.is_empty() { 1059 components.push(IdentLike(ident_like)); 1060 } 1061 1062 // With proc macros the span can refer to anything, the source may be too short, 1063 // or too long, or non-ASCII. It only makes sense to break our span into components 1064 // if its underlying text is identical to our float literal. 1065 let span = self.token.span; 1066 let can_take_span_apart = 1067 || self.span_to_snippet(span).as_deref() == Ok(float_str).as_deref(); 1068 1069 match &*components { 1070 // 1e2 1071 [IdentLike(i)] => { 1072 DestructuredFloat::Single(Symbol::intern(&i), span) 1073 } 1074 // 1. 1075 [IdentLike(i), Punct('.')] => { 1076 let (ident_span, dot_span) = if can_take_span_apart() { 1077 let (span, ident_len) = (span.data(), BytePos::from_usize(i.len())); 1078 let ident_span = span.with_hi(span.lo + ident_len); 1079 let dot_span = span.with_lo(span.lo + ident_len); 1080 (ident_span, dot_span) 1081 } else { 1082 (span, span) 1083 }; 1084 let symbol = Symbol::intern(&i); 1085 DestructuredFloat::TrailingDot(symbol, ident_span, dot_span) 1086 } 1087 // 1.2 | 1.2e3 1088 [IdentLike(i1), Punct('.'), IdentLike(i2)] => { 1089 let (ident1_span, dot_span, ident2_span) = if can_take_span_apart() { 1090 let (span, ident1_len) = (span.data(), BytePos::from_usize(i1.len())); 1091 let ident1_span = span.with_hi(span.lo + ident1_len); 1092 let dot_span = span 1093 .with_lo(span.lo + ident1_len) 1094 .with_hi(span.lo + ident1_len + BytePos(1)); 1095 let ident2_span = self.token.span.with_lo(span.lo + ident1_len + BytePos(1)); 1096 (ident1_span, dot_span, ident2_span) 1097 } else { 1098 (span, span, span) 1099 }; 1100 let symbol1 = Symbol::intern(&i1); 1101 let symbol2 = Symbol::intern(&i2); 1102 DestructuredFloat::MiddleDot(symbol1, ident1_span, dot_span, symbol2, ident2_span) 1103 } 1104 // 1e+ | 1e- (recovered) 1105 [IdentLike(_), Punct('+' | '-')] | 1106 // 1e+2 | 1e-2 1107 [IdentLike(_), Punct('+' | '-'), IdentLike(_)] | 1108 // 1.2e+ | 1.2e- 1109 [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-')] | 1110 // 1.2e+3 | 1.2e-3 1111 [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-'), IdentLike(_)] => { 1112 // See the FIXME about `TokenCursor` above. 1113 self.error_unexpected_after_dot(); 1114 DestructuredFloat::Error 1115 } 1116 _ => panic!("unexpected components in a float token: {:?}", components), 1117 } 1118 } 1119 parse_expr_tuple_field_access_float( &mut self, lo: Span, base: P<Expr>, float: Symbol, suffix: Option<Symbol>, ) -> P<Expr>1120 fn parse_expr_tuple_field_access_float( 1121 &mut self, 1122 lo: Span, 1123 base: P<Expr>, 1124 float: Symbol, 1125 suffix: Option<Symbol>, 1126 ) -> P<Expr> { 1127 match self.break_up_float(float) { 1128 // 1e2 1129 DestructuredFloat::Single(sym, _sp) => { 1130 self.parse_expr_tuple_field_access(lo, base, sym, suffix, None) 1131 } 1132 // 1. 1133 DestructuredFloat::TrailingDot(sym, ident_span, dot_span) => { 1134 assert!(suffix.is_none()); 1135 self.token = Token::new(token::Ident(sym, false), ident_span); 1136 let next_token = (Token::new(token::Dot, dot_span), self.token_spacing); 1137 self.parse_expr_tuple_field_access(lo, base, sym, None, Some(next_token)) 1138 } 1139 // 1.2 | 1.2e3 1140 DestructuredFloat::MiddleDot(symbol1, ident1_span, dot_span, symbol2, ident2_span) => { 1141 self.token = Token::new(token::Ident(symbol1, false), ident1_span); 1142 // This needs to be `Spacing::Alone` to prevent regressions. 1143 // See issue #76399 and PR #76285 for more details 1144 let next_token1 = (Token::new(token::Dot, dot_span), Spacing::Alone); 1145 let base1 = 1146 self.parse_expr_tuple_field_access(lo, base, symbol1, None, Some(next_token1)); 1147 let next_token2 = Token::new(token::Ident(symbol2, false), ident2_span); 1148 self.bump_with((next_token2, self.token_spacing)); // `.` 1149 self.parse_expr_tuple_field_access(lo, base1, symbol2, suffix, None) 1150 } 1151 DestructuredFloat::Error => base, 1152 } 1153 } 1154 parse_field_name_maybe_tuple(&mut self) -> PResult<'a, ThinVec<Ident>>1155 fn parse_field_name_maybe_tuple(&mut self) -> PResult<'a, ThinVec<Ident>> { 1156 let token::Literal(token::Lit { kind: token::Float, symbol, suffix }) = self.token.kind 1157 else { 1158 return Ok(thin_vec![self.parse_field_name()?]); 1159 }; 1160 Ok(match self.break_up_float(symbol) { 1161 // 1e2 1162 DestructuredFloat::Single(sym, sp) => { 1163 self.bump(); 1164 thin_vec![Ident::new(sym, sp)] 1165 } 1166 // 1. 1167 DestructuredFloat::TrailingDot(sym, sym_span, dot_span) => { 1168 assert!(suffix.is_none()); 1169 // Analogous to `Self::break_and_eat` 1170 self.token_cursor.break_last_token = true; 1171 // This might work, in cases like `1. 2`, and might not, 1172 // in cases like `offset_of!(Ty, 1.)`. It depends on what comes 1173 // after the float-like token, and therefore we have to make 1174 // the other parts of the parser think that there is a dot literal. 1175 self.token = Token::new(token::Ident(sym, false), sym_span); 1176 self.bump_with((Token::new(token::Dot, dot_span), self.token_spacing)); 1177 thin_vec![Ident::new(sym, sym_span)] 1178 } 1179 // 1.2 | 1.2e3 1180 DestructuredFloat::MiddleDot(symbol1, ident1_span, _dot_span, symbol2, ident2_span) => { 1181 self.bump(); 1182 thin_vec![Ident::new(symbol1, ident1_span), Ident::new(symbol2, ident2_span)] 1183 } 1184 DestructuredFloat::Error => { 1185 self.bump(); 1186 thin_vec![Ident::new(symbol, self.prev_token.span)] 1187 } 1188 }) 1189 } 1190 parse_expr_tuple_field_access( &mut self, lo: Span, base: P<Expr>, field: Symbol, suffix: Option<Symbol>, next_token: Option<(Token, Spacing)>, ) -> P<Expr>1191 fn parse_expr_tuple_field_access( 1192 &mut self, 1193 lo: Span, 1194 base: P<Expr>, 1195 field: Symbol, 1196 suffix: Option<Symbol>, 1197 next_token: Option<(Token, Spacing)>, 1198 ) -> P<Expr> { 1199 match next_token { 1200 Some(next_token) => self.bump_with(next_token), 1201 None => self.bump(), 1202 } 1203 let span = self.prev_token.span; 1204 let field = ExprKind::Field(base, Ident::new(field, span)); 1205 if let Some(suffix) = suffix { 1206 self.expect_no_tuple_index_suffix(span, suffix); 1207 } 1208 self.mk_expr(lo.to(span), field) 1209 } 1210 1211 /// Parse a function call expression, `expr(...)`. parse_expr_fn_call(&mut self, lo: Span, fun: P<Expr>) -> P<Expr>1212 fn parse_expr_fn_call(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> { 1213 let snapshot = if self.token.kind == token::OpenDelim(Delimiter::Parenthesis) { 1214 Some((self.create_snapshot_for_diagnostic(), fun.kind.clone())) 1215 } else { 1216 None 1217 }; 1218 let open_paren = self.token.span; 1219 1220 let mut seq = self 1221 .parse_expr_paren_seq() 1222 .map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args))); 1223 if let Some(expr) = 1224 self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot) 1225 { 1226 return expr; 1227 } 1228 self.recover_seq_parse_error(Delimiter::Parenthesis, lo, seq) 1229 } 1230 1231 /// If we encounter a parser state that looks like the user has written a `struct` literal with 1232 /// parentheses instead of braces, recover the parser state and provide suggestions. 1233 #[instrument(skip(self, seq, snapshot), level = "trace")] maybe_recover_struct_lit_bad_delims( &mut self, lo: Span, open_paren: Span, seq: &mut PResult<'a, P<Expr>>, snapshot: Option<(SnapshotParser<'a>, ExprKind)>, ) -> Option<P<Expr>>1234 fn maybe_recover_struct_lit_bad_delims( 1235 &mut self, 1236 lo: Span, 1237 open_paren: Span, 1238 seq: &mut PResult<'a, P<Expr>>, 1239 snapshot: Option<(SnapshotParser<'a>, ExprKind)>, 1240 ) -> Option<P<Expr>> { 1241 if !self.may_recover() { 1242 return None; 1243 } 1244 match (seq.as_mut(), snapshot) { 1245 (Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => { 1246 snapshot.bump(); // `(` 1247 match snapshot.parse_struct_fields(path.clone(), false, Delimiter::Parenthesis) { 1248 Ok((fields, ..)) 1249 if snapshot.eat(&token::CloseDelim(Delimiter::Parenthesis)) => 1250 { 1251 // We are certain we have `Enum::Foo(a: 3, b: 4)`, suggest 1252 // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`. 1253 self.restore_snapshot(snapshot); 1254 let close_paren = self.prev_token.span; 1255 let span = lo.to(close_paren); 1256 // filter shorthand fields 1257 let fields: Vec<_> = 1258 fields.into_iter().filter(|field| !field.is_shorthand).collect(); 1259 1260 if !fields.is_empty() && 1261 // `token.kind` should not be compared here. 1262 // This is because the `snapshot.token.kind` is treated as the same as 1263 // that of the open delim in `TokenTreesReader::parse_token_tree`, even if they are different. 1264 self.span_to_snippet(close_paren).is_ok_and(|snippet| snippet == ")") 1265 { 1266 let mut replacement_err = errors::ParenthesesWithStructFields { 1267 span, 1268 r#type: path, 1269 braces_for_struct: errors::BracesForStructLiteral { 1270 first: open_paren, 1271 second: close_paren, 1272 }, 1273 no_fields_for_fn: errors::NoFieldsForFnCall { 1274 fields: fields 1275 .into_iter() 1276 .map(|field| field.span.until(field.expr.span)) 1277 .collect(), 1278 }, 1279 } 1280 .into_diagnostic(&self.sess.span_diagnostic); 1281 replacement_err.emit(); 1282 1283 let old_err = mem::replace(err, replacement_err); 1284 old_err.cancel(); 1285 } else { 1286 err.emit(); 1287 } 1288 return Some(self.mk_expr_err(span)); 1289 } 1290 Ok(_) => {} 1291 Err(err) => err.cancel(), 1292 } 1293 } 1294 _ => {} 1295 } 1296 None 1297 } 1298 1299 /// Parse an indexing expression `expr[...]`. parse_expr_index(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>>1300 fn parse_expr_index(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> { 1301 let prev_span = self.prev_token.span; 1302 let open_delim_span = self.token.span; 1303 self.bump(); // `[` 1304 let index = self.parse_expr()?; 1305 self.suggest_missing_semicolon_before_array(prev_span, open_delim_span)?; 1306 self.expect(&token::CloseDelim(Delimiter::Bracket))?; 1307 Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_index(base, index))) 1308 } 1309 1310 /// Assuming we have just parsed `.`, continue parsing into an expression. parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>>1311 fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> { 1312 if self.token.uninterpolated_span().rust_2018() && self.eat_keyword(kw::Await) { 1313 return Ok(self.mk_await_expr(self_arg, lo)); 1314 } 1315 1316 let fn_span_lo = self.token.span; 1317 let mut seg = self.parse_path_segment(PathStyle::Expr, None)?; 1318 self.check_trailing_angle_brackets(&seg, &[&token::OpenDelim(Delimiter::Parenthesis)]); 1319 self.check_turbofish_missing_angle_brackets(&mut seg); 1320 1321 if self.check(&token::OpenDelim(Delimiter::Parenthesis)) { 1322 // Method call `expr.f()` 1323 let args = self.parse_expr_paren_seq()?; 1324 let fn_span = fn_span_lo.to(self.prev_token.span); 1325 let span = lo.to(self.prev_token.span); 1326 Ok(self.mk_expr( 1327 span, 1328 ExprKind::MethodCall(Box::new(ast::MethodCall { 1329 seg, 1330 receiver: self_arg, 1331 args, 1332 span: fn_span, 1333 })), 1334 )) 1335 } else { 1336 // Field access `expr.f` 1337 if let Some(args) = seg.args { 1338 self.sess.emit_err(errors::FieldExpressionWithGeneric(args.span())); 1339 } 1340 1341 let span = lo.to(self.prev_token.span); 1342 Ok(self.mk_expr(span, ExprKind::Field(self_arg, seg.ident))) 1343 } 1344 } 1345 1346 /// At the bottom (top?) of the precedence hierarchy, 1347 /// Parses things like parenthesized exprs, macros, `return`, etc. 1348 /// 1349 /// N.B., this does not parse outer attributes, and is private because it only works 1350 /// correctly if called from `parse_dot_or_call_expr()`. parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>>1351 fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> { 1352 maybe_recover_from_interpolated_ty_qpath!(self, true); 1353 maybe_whole_expr!(self); 1354 1355 // Outer attributes are already parsed and will be 1356 // added to the return value after the fact. 1357 1358 // Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`. 1359 let lo = self.token.span; 1360 if let token::Literal(_) = self.token.kind { 1361 // This match arm is a special-case of the `_` match arm below and 1362 // could be removed without changing functionality, but it's faster 1363 // to have it here, especially for programs with large constants. 1364 self.parse_expr_lit() 1365 } else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) { 1366 self.parse_expr_tuple_parens() 1367 } else if self.check(&token::OpenDelim(Delimiter::Brace)) { 1368 self.parse_expr_block(None, lo, BlockCheckMode::Default) 1369 } else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) { 1370 self.parse_expr_closure().map_err(|mut err| { 1371 // If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }` 1372 // then suggest parens around the lhs. 1373 if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&lo) { 1374 err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); 1375 } 1376 err 1377 }) 1378 } else if self.check(&token::OpenDelim(Delimiter::Bracket)) { 1379 self.parse_expr_array_or_repeat(Delimiter::Bracket) 1380 } else if self.is_builtin() { 1381 self.parse_expr_builtin() 1382 } else if self.check_path() { 1383 self.parse_expr_path_start() 1384 } else if self.check_keyword(kw::Move) 1385 || self.check_keyword(kw::Static) 1386 || self.check_const_closure() 1387 { 1388 self.parse_expr_closure() 1389 } else if self.eat_keyword(kw::If) { 1390 self.parse_expr_if() 1391 } else if self.check_keyword(kw::For) { 1392 if self.choose_generics_over_qpath(1) { 1393 self.parse_expr_closure() 1394 } else { 1395 assert!(self.eat_keyword(kw::For)); 1396 self.parse_expr_for(None, self.prev_token.span) 1397 } 1398 } else if self.eat_keyword(kw::While) { 1399 self.parse_expr_while(None, self.prev_token.span) 1400 } else if let Some(label) = self.eat_label() { 1401 self.parse_expr_labeled(label, true) 1402 } else if self.eat_keyword(kw::Loop) { 1403 let sp = self.prev_token.span; 1404 self.parse_expr_loop(None, self.prev_token.span).map_err(|mut err| { 1405 err.span_label(sp, "while parsing this `loop` expression"); 1406 err 1407 }) 1408 } else if self.eat_keyword(kw::Match) { 1409 let match_sp = self.prev_token.span; 1410 self.parse_expr_match().map_err(|mut err| { 1411 err.span_label(match_sp, "while parsing this `match` expression"); 1412 err 1413 }) 1414 } else if self.eat_keyword(kw::Unsafe) { 1415 let sp = self.prev_token.span; 1416 self.parse_expr_block(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err( 1417 |mut err| { 1418 err.span_label(sp, "while parsing this `unsafe` expression"); 1419 err 1420 }, 1421 ) 1422 } else if self.check_inline_const(0) { 1423 self.parse_const_block(lo.to(self.token.span), false) 1424 } else if self.may_recover() && self.is_do_catch_block() { 1425 self.recover_do_catch() 1426 } else if self.is_try_block() { 1427 self.expect_keyword(kw::Try)?; 1428 self.parse_try_block(lo) 1429 } else if self.eat_keyword(kw::Return) { 1430 self.parse_expr_return() 1431 } else if self.eat_keyword(kw::Continue) { 1432 self.parse_expr_continue(lo) 1433 } else if self.eat_keyword(kw::Break) { 1434 self.parse_expr_break() 1435 } else if self.eat_keyword(kw::Yield) { 1436 self.parse_expr_yield() 1437 } else if self.is_do_yeet() { 1438 self.parse_expr_yeet() 1439 } else if self.eat_keyword(kw::Become) { 1440 self.parse_expr_become() 1441 } else if self.check_keyword(kw::Let) { 1442 self.parse_expr_let() 1443 } else if self.eat_keyword(kw::Underscore) { 1444 Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore)) 1445 } else if self.token.uninterpolated_span().rust_2018() { 1446 // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly. 1447 if self.check_keyword(kw::Async) { 1448 if self.is_async_block() { 1449 // Check for `async {` and `async move {`. 1450 self.parse_async_block() 1451 } else { 1452 self.parse_expr_closure() 1453 } 1454 } else if self.eat_keyword(kw::Await) { 1455 self.recover_incorrect_await_syntax(lo, self.prev_token.span) 1456 } else { 1457 self.parse_expr_lit() 1458 } 1459 } else { 1460 self.parse_expr_lit() 1461 } 1462 } 1463 parse_expr_lit(&mut self) -> PResult<'a, P<Expr>>1464 fn parse_expr_lit(&mut self) -> PResult<'a, P<Expr>> { 1465 let lo = self.token.span; 1466 match self.parse_opt_token_lit() { 1467 Some((token_lit, _)) => { 1468 let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(token_lit)); 1469 self.maybe_recover_from_bad_qpath(expr) 1470 } 1471 None => self.try_macro_suggestion(), 1472 } 1473 } 1474 parse_expr_tuple_parens(&mut self) -> PResult<'a, P<Expr>>1475 fn parse_expr_tuple_parens(&mut self) -> PResult<'a, P<Expr>> { 1476 let lo = self.token.span; 1477 self.expect(&token::OpenDelim(Delimiter::Parenthesis))?; 1478 let (es, trailing_comma) = match self.parse_seq_to_end( 1479 &token::CloseDelim(Delimiter::Parenthesis), 1480 SeqSep::trailing_allowed(token::Comma), 1481 |p| p.parse_expr_catch_underscore(), 1482 ) { 1483 Ok(x) => x, 1484 Err(err) => { 1485 return Ok(self.recover_seq_parse_error(Delimiter::Parenthesis, lo, Err(err))); 1486 } 1487 }; 1488 let kind = if es.len() == 1 && !trailing_comma { 1489 // `(e)` is parenthesized `e`. 1490 ExprKind::Paren(es.into_iter().next().unwrap()) 1491 } else { 1492 // `(e,)` is a tuple with only one field, `e`. 1493 ExprKind::Tup(es) 1494 }; 1495 let expr = self.mk_expr(lo.to(self.prev_token.span), kind); 1496 self.maybe_recover_from_bad_qpath(expr) 1497 } 1498 parse_expr_array_or_repeat(&mut self, close_delim: Delimiter) -> PResult<'a, P<Expr>>1499 fn parse_expr_array_or_repeat(&mut self, close_delim: Delimiter) -> PResult<'a, P<Expr>> { 1500 let lo = self.token.span; 1501 self.bump(); // `[` or other open delim 1502 1503 let close = &token::CloseDelim(close_delim); 1504 let kind = if self.eat(close) { 1505 // Empty vector 1506 ExprKind::Array(ThinVec::new()) 1507 } else { 1508 // Non-empty vector 1509 let first_expr = self.parse_expr()?; 1510 if self.eat(&token::Semi) { 1511 // Repeating array syntax: `[ 0; 512 ]` 1512 let count = self.parse_expr_anon_const()?; 1513 self.expect(close)?; 1514 ExprKind::Repeat(first_expr, count) 1515 } else if self.eat(&token::Comma) { 1516 // Vector with two or more elements. 1517 let sep = SeqSep::trailing_allowed(token::Comma); 1518 let (mut exprs, _) = self.parse_seq_to_end(close, sep, |p| p.parse_expr())?; 1519 exprs.insert(0, first_expr); 1520 ExprKind::Array(exprs) 1521 } else { 1522 // Vector with one element 1523 self.expect(close)?; 1524 ExprKind::Array(thin_vec![first_expr]) 1525 } 1526 }; 1527 let expr = self.mk_expr(lo.to(self.prev_token.span), kind); 1528 self.maybe_recover_from_bad_qpath(expr) 1529 } 1530 parse_expr_path_start(&mut self) -> PResult<'a, P<Expr>>1531 fn parse_expr_path_start(&mut self) -> PResult<'a, P<Expr>> { 1532 let maybe_eq_tok = self.prev_token.clone(); 1533 let (qself, path) = if self.eat_lt() { 1534 let lt_span = self.prev_token.span; 1535 let (qself, path) = self.parse_qpath(PathStyle::Expr).map_err(|mut err| { 1536 // Suggests using '<=' if there is an error parsing qpath when the previous token 1537 // is an '=' token. Only emits suggestion if the '<' token and '=' token are 1538 // directly adjacent (i.e. '=<') 1539 if maybe_eq_tok.kind == TokenKind::Eq && maybe_eq_tok.span.hi() == lt_span.lo() { 1540 let eq_lt = maybe_eq_tok.span.to(lt_span); 1541 err.span_suggestion(eq_lt, "did you mean", "<=", Applicability::Unspecified); 1542 } 1543 err 1544 })?; 1545 (Some(qself), path) 1546 } else { 1547 (None, self.parse_path(PathStyle::Expr)?) 1548 }; 1549 1550 // `!`, as an operator, is prefix, so we know this isn't that. 1551 let (span, kind) = if self.eat(&token::Not) { 1552 // MACRO INVOCATION expression 1553 if qself.is_some() { 1554 self.sess.emit_err(errors::MacroInvocationWithQualifiedPath(path.span)); 1555 } 1556 let lo = path.span; 1557 let mac = P(MacCall { 1558 path, 1559 args: self.parse_delim_args()?, 1560 }); 1561 (lo.to(self.prev_token.span), ExprKind::MacCall(mac)) 1562 } else if self.check(&token::OpenDelim(Delimiter::Brace)) 1563 && let Some(expr) = self.maybe_parse_struct_expr(&qself, &path) 1564 { 1565 if qself.is_some() { 1566 self.sess.gated_spans.gate(sym::more_qualified_paths, path.span); 1567 } 1568 return expr; 1569 } else { 1570 (path.span, ExprKind::Path(qself, path)) 1571 }; 1572 1573 let expr = self.mk_expr(span, kind); 1574 self.maybe_recover_from_bad_qpath(expr) 1575 } 1576 1577 /// Parse `'label: $expr`. The label is already parsed. parse_expr_labeled( &mut self, label_: Label, mut consume_colon: bool, ) -> PResult<'a, P<Expr>>1578 pub(super) fn parse_expr_labeled( 1579 &mut self, 1580 label_: Label, 1581 mut consume_colon: bool, 1582 ) -> PResult<'a, P<Expr>> { 1583 let lo = label_.ident.span; 1584 let label = Some(label_); 1585 let ate_colon = self.eat(&token::Colon); 1586 let expr = if self.eat_keyword(kw::While) { 1587 self.parse_expr_while(label, lo) 1588 } else if self.eat_keyword(kw::For) { 1589 self.parse_expr_for(label, lo) 1590 } else if self.eat_keyword(kw::Loop) { 1591 self.parse_expr_loop(label, lo) 1592 } else if self.check_noexpect(&token::OpenDelim(Delimiter::Brace)) 1593 || self.token.is_whole_block() 1594 { 1595 self.parse_expr_block(label, lo, BlockCheckMode::Default) 1596 } else if !ate_colon 1597 && self.may_recover() 1598 && (matches!(self.token.kind, token::CloseDelim(_) | token::Comma) 1599 || self.token.is_op()) 1600 { 1601 let (lit, _) = 1602 self.recover_unclosed_char(label_.ident, Parser::mk_token_lit_char, |self_| { 1603 self_.sess.create_err(errors::UnexpectedTokenAfterLabel { 1604 span: self_.token.span, 1605 remove_label: None, 1606 enclose_in_block: None, 1607 }) 1608 }); 1609 consume_colon = false; 1610 Ok(self.mk_expr(lo, ExprKind::Lit(lit))) 1611 } else if !ate_colon 1612 && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt)) 1613 { 1614 // We're probably inside of a `Path<'a>` that needs a turbofish 1615 self.sess.emit_err(errors::UnexpectedTokenAfterLabel { 1616 span: self.token.span, 1617 remove_label: None, 1618 enclose_in_block: None, 1619 }); 1620 consume_colon = false; 1621 Ok(self.mk_expr_err(lo)) 1622 } else { 1623 let mut err = errors::UnexpectedTokenAfterLabel { 1624 span: self.token.span, 1625 remove_label: None, 1626 enclose_in_block: None, 1627 }; 1628 1629 // Continue as an expression in an effort to recover on `'label: non_block_expr`. 1630 let expr = self.parse_expr().map(|expr| { 1631 let span = expr.span; 1632 1633 let found_labeled_breaks = { 1634 struct FindLabeledBreaksVisitor(bool); 1635 1636 impl<'ast> Visitor<'ast> for FindLabeledBreaksVisitor { 1637 fn visit_expr_post(&mut self, ex: &'ast Expr) { 1638 if let ExprKind::Break(Some(_label), _) = ex.kind { 1639 self.0 = true; 1640 } 1641 } 1642 } 1643 1644 let mut vis = FindLabeledBreaksVisitor(false); 1645 vis.visit_expr(&expr); 1646 vis.0 1647 }; 1648 1649 // Suggestion involves adding a labeled block. 1650 // 1651 // If there are no breaks that may use this label, suggest removing the label and 1652 // recover to the unmodified expression. 1653 if !found_labeled_breaks { 1654 err.remove_label = Some(lo.until(span)); 1655 1656 return expr; 1657 } 1658 1659 err.enclose_in_block = Some(errors::UnexpectedTokenAfterLabelSugg { 1660 left: span.shrink_to_lo(), 1661 right: span.shrink_to_hi(), 1662 }); 1663 1664 // Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to suppress future errors about `break 'label`. 1665 let stmt = self.mk_stmt(span, StmtKind::Expr(expr)); 1666 let blk = self.mk_block(thin_vec![stmt], BlockCheckMode::Default, span); 1667 self.mk_expr(span, ExprKind::Block(blk, label)) 1668 }); 1669 1670 self.sess.emit_err(err); 1671 expr 1672 }?; 1673 1674 if !ate_colon && consume_colon { 1675 self.sess.emit_err(errors::RequireColonAfterLabeledExpression { 1676 span: expr.span, 1677 label: lo, 1678 label_end: lo.shrink_to_hi(), 1679 }); 1680 } 1681 1682 Ok(expr) 1683 } 1684 1685 /// Emit an error when a char is parsed as a lifetime because of a missing quote. recover_unclosed_char<L>( &self, lifetime: Ident, mk_lit_char: impl FnOnce(Symbol, Span) -> L, err: impl FnOnce(&Self) -> DiagnosticBuilder<'a, ErrorGuaranteed>, ) -> L1686 pub(super) fn recover_unclosed_char<L>( 1687 &self, 1688 lifetime: Ident, 1689 mk_lit_char: impl FnOnce(Symbol, Span) -> L, 1690 err: impl FnOnce(&Self) -> DiagnosticBuilder<'a, ErrorGuaranteed>, 1691 ) -> L { 1692 if let Some(mut diag) = 1693 self.sess.span_diagnostic.steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar) 1694 { 1695 diag.span_suggestion_verbose( 1696 lifetime.span.shrink_to_hi(), 1697 "add `'` to close the char literal", 1698 "'", 1699 Applicability::MaybeIncorrect, 1700 ) 1701 .emit(); 1702 } else { 1703 err(self) 1704 .span_suggestion_verbose( 1705 lifetime.span.shrink_to_hi(), 1706 "add `'` to close the char literal", 1707 "'", 1708 Applicability::MaybeIncorrect, 1709 ) 1710 .emit(); 1711 } 1712 let name = lifetime.without_first_quote().name; 1713 mk_lit_char(name, lifetime.span) 1714 } 1715 1716 /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead. recover_do_catch(&mut self) -> PResult<'a, P<Expr>>1717 fn recover_do_catch(&mut self) -> PResult<'a, P<Expr>> { 1718 let lo = self.token.span; 1719 1720 self.bump(); // `do` 1721 self.bump(); // `catch` 1722 1723 let span = lo.to(self.prev_token.span); 1724 self.sess.emit_err(errors::DoCatchSyntaxRemoved { span }); 1725 1726 self.parse_try_block(lo) 1727 } 1728 1729 /// Parse an expression if the token can begin one. parse_expr_opt(&mut self) -> PResult<'a, Option<P<Expr>>>1730 fn parse_expr_opt(&mut self) -> PResult<'a, Option<P<Expr>>> { 1731 Ok(if self.token.can_begin_expr() { Some(self.parse_expr()?) } else { None }) 1732 } 1733 1734 /// Parse `"return" expr?`. parse_expr_return(&mut self) -> PResult<'a, P<Expr>>1735 fn parse_expr_return(&mut self) -> PResult<'a, P<Expr>> { 1736 let lo = self.prev_token.span; 1737 let kind = ExprKind::Ret(self.parse_expr_opt()?); 1738 let expr = self.mk_expr(lo.to(self.prev_token.span), kind); 1739 self.maybe_recover_from_bad_qpath(expr) 1740 } 1741 1742 /// Parse `"do" "yeet" expr?`. parse_expr_yeet(&mut self) -> PResult<'a, P<Expr>>1743 fn parse_expr_yeet(&mut self) -> PResult<'a, P<Expr>> { 1744 let lo = self.token.span; 1745 1746 self.bump(); // `do` 1747 self.bump(); // `yeet` 1748 1749 let kind = ExprKind::Yeet(self.parse_expr_opt()?); 1750 1751 let span = lo.to(self.prev_token.span); 1752 self.sess.gated_spans.gate(sym::yeet_expr, span); 1753 let expr = self.mk_expr(span, kind); 1754 self.maybe_recover_from_bad_qpath(expr) 1755 } 1756 1757 /// Parse `"become" expr`, with `"become"` token already eaten. parse_expr_become(&mut self) -> PResult<'a, P<Expr>>1758 fn parse_expr_become(&mut self) -> PResult<'a, P<Expr>> { 1759 let lo = self.prev_token.span; 1760 let kind = ExprKind::Become(self.parse_expr()?); 1761 let span = lo.to(self.prev_token.span); 1762 self.sess.gated_spans.gate(sym::explicit_tail_calls, span); 1763 let expr = self.mk_expr(span, kind); 1764 self.maybe_recover_from_bad_qpath(expr) 1765 } 1766 1767 /// Parse `"break" (('label (:? expr)?) | expr?)` with `"break"` token already eaten. 1768 /// If the label is followed immediately by a `:` token, the label and `:` are 1769 /// parsed as part of the expression (i.e. a labeled loop). The language team has 1770 /// decided in #87026 to require parentheses as a visual aid to avoid confusion if 1771 /// the break expression of an unlabeled break is a labeled loop (as in 1772 /// `break 'lbl: loop {}`); a labeled break with an unlabeled loop as its value 1773 /// expression only gets a warning for compatibility reasons; and a labeled break 1774 /// with a labeled loop does not even get a warning because there is no ambiguity. parse_expr_break(&mut self) -> PResult<'a, P<Expr>>1775 fn parse_expr_break(&mut self) -> PResult<'a, P<Expr>> { 1776 let lo = self.prev_token.span; 1777 let mut label = self.eat_label(); 1778 let kind = if self.token == token::Colon && let Some(label) = label.take() { 1779 // The value expression can be a labeled loop, see issue #86948, e.g.: 1780 // `loop { break 'label: loop { break 'label 42; }; }` 1781 let lexpr = self.parse_expr_labeled(label, true)?; 1782 self.sess.emit_err(errors::LabeledLoopInBreak { 1783 span: lexpr.span, 1784 sub: errors::WrapExpressionInParentheses { 1785 left: lexpr.span.shrink_to_lo(), 1786 right: lexpr.span.shrink_to_hi(), 1787 }, 1788 }); 1789 Some(lexpr) 1790 } else if self.token != token::OpenDelim(Delimiter::Brace) 1791 || !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) 1792 { 1793 let mut expr = self.parse_expr_opt()?; 1794 if let Some(expr) = &mut expr { 1795 if label.is_some() 1796 && matches!( 1797 expr.kind, 1798 ExprKind::While(_, _, None) 1799 | ExprKind::ForLoop(_, _, _, None) 1800 | ExprKind::Loop(_, None, _) 1801 | ExprKind::Block(_, None) 1802 ) 1803 { 1804 self.sess.buffer_lint_with_diagnostic( 1805 BREAK_WITH_LABEL_AND_LOOP, 1806 lo.to(expr.span), 1807 ast::CRATE_NODE_ID, 1808 "this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression", 1809 BuiltinLintDiagnostics::BreakWithLabelAndLoop(expr.span), 1810 ); 1811 } 1812 1813 // Recover `break label aaaaa` 1814 if self.may_recover() 1815 && let ExprKind::Path(None, p) = &expr.kind 1816 && let [segment] = &*p.segments 1817 && let &ast::PathSegment { ident, args: None, .. } = segment 1818 && let Some(next) = self.parse_expr_opt()? 1819 { 1820 label = Some(self.recover_ident_into_label(ident)); 1821 *expr = next; 1822 } 1823 } 1824 1825 expr 1826 } else { 1827 None 1828 }; 1829 let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Break(label, kind)); 1830 self.maybe_recover_from_bad_qpath(expr) 1831 } 1832 1833 /// Parse `"continue" label?`. parse_expr_continue(&mut self, lo: Span) -> PResult<'a, P<Expr>>1834 fn parse_expr_continue(&mut self, lo: Span) -> PResult<'a, P<Expr>> { 1835 let mut label = self.eat_label(); 1836 1837 // Recover `continue label` -> `continue 'label` 1838 if self.may_recover() 1839 && label.is_none() 1840 && let Some((ident, _)) = self.token.ident() 1841 { 1842 self.bump(); 1843 label = Some(self.recover_ident_into_label(ident)); 1844 } 1845 1846 let kind = ExprKind::Continue(label); 1847 Ok(self.mk_expr(lo.to(self.prev_token.span), kind)) 1848 } 1849 1850 /// Parse `"yield" expr?`. parse_expr_yield(&mut self) -> PResult<'a, P<Expr>>1851 fn parse_expr_yield(&mut self) -> PResult<'a, P<Expr>> { 1852 let lo = self.prev_token.span; 1853 let kind = ExprKind::Yield(self.parse_expr_opt()?); 1854 let span = lo.to(self.prev_token.span); 1855 self.sess.gated_spans.gate(sym::generators, span); 1856 let expr = self.mk_expr(span, kind); 1857 self.maybe_recover_from_bad_qpath(expr) 1858 } 1859 1860 /// Parse `builtin # ident(args,*)`. parse_expr_builtin(&mut self) -> PResult<'a, P<Expr>>1861 fn parse_expr_builtin(&mut self) -> PResult<'a, P<Expr>> { 1862 self.parse_builtin(|this, lo, ident| { 1863 if ident.name == sym::offset_of { 1864 return Ok(Some(this.parse_expr_offset_of(lo)?)); 1865 } 1866 1867 Ok(None) 1868 }) 1869 } 1870 parse_builtin<T>( &mut self, parse: impl FnOnce(&mut Parser<'a>, Span, Ident) -> PResult<'a, Option<T>>, ) -> PResult<'a, T>1871 pub(crate) fn parse_builtin<T>( 1872 &mut self, 1873 parse: impl FnOnce(&mut Parser<'a>, Span, Ident) -> PResult<'a, Option<T>>, 1874 ) -> PResult<'a, T> { 1875 let lo = self.token.span; 1876 1877 self.bump(); // `builtin` 1878 self.bump(); // `#` 1879 1880 let Some((ident, false)) = self.token.ident() else { 1881 let err = errors::ExpectedBuiltinIdent { span: self.token.span } 1882 .into_diagnostic(&self.sess.span_diagnostic); 1883 return Err(err); 1884 }; 1885 self.sess.gated_spans.gate(sym::builtin_syntax, ident.span); 1886 self.bump(); 1887 1888 self.expect(&TokenKind::OpenDelim(Delimiter::Parenthesis))?; 1889 let ret = if let Some(res) = parse(self, lo, ident)? { 1890 Ok(res) 1891 } else { 1892 let err = errors::UnknownBuiltinConstruct { span: lo.to(ident.span), name: ident.name } 1893 .into_diagnostic(&self.sess.span_diagnostic); 1894 return Err(err); 1895 }; 1896 self.expect(&TokenKind::CloseDelim(Delimiter::Parenthesis))?; 1897 1898 ret 1899 } 1900 parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, P<Expr>>1901 pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, P<Expr>> { 1902 let container = self.parse_ty()?; 1903 self.expect(&TokenKind::Comma)?; 1904 1905 let seq_sep = SeqSep { sep: Some(token::Dot), trailing_sep_allowed: false }; 1906 let (fields, _trailing, _recovered) = self.parse_seq_to_before_end( 1907 &TokenKind::CloseDelim(Delimiter::Parenthesis), 1908 seq_sep, 1909 Parser::parse_field_name_maybe_tuple, 1910 )?; 1911 let fields = fields.into_iter().flatten().collect::<Vec<_>>(); 1912 let span = lo.to(self.token.span); 1913 Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields.into()))) 1914 } 1915 1916 /// Returns a string literal if the next token is a string literal. 1917 /// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind, 1918 /// and returns `None` if the next token is not literal at all. parse_str_lit(&mut self) -> Result<ast::StrLit, Option<MetaItemLit>>1919 pub fn parse_str_lit(&mut self) -> Result<ast::StrLit, Option<MetaItemLit>> { 1920 match self.parse_opt_meta_item_lit() { 1921 Some(lit) => match lit.kind { 1922 ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit { 1923 style, 1924 symbol: lit.symbol, 1925 suffix: lit.suffix, 1926 span: lit.span, 1927 symbol_unescaped, 1928 }), 1929 _ => Err(Some(lit)), 1930 }, 1931 None => Err(None), 1932 } 1933 } 1934 mk_token_lit_char(name: Symbol, span: Span) -> (token::Lit, Span)1935 pub(crate) fn mk_token_lit_char(name: Symbol, span: Span) -> (token::Lit, Span) { 1936 (token::Lit { symbol: name, suffix: None, kind: token::Char }, span) 1937 } 1938 mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit1939 fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit { 1940 ast::MetaItemLit { 1941 symbol: name, 1942 suffix: None, 1943 kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')), 1944 span, 1945 } 1946 } 1947 handle_missing_lit<L>( &mut self, mk_lit_char: impl FnOnce(Symbol, Span) -> L, ) -> PResult<'a, L>1948 fn handle_missing_lit<L>( 1949 &mut self, 1950 mk_lit_char: impl FnOnce(Symbol, Span) -> L, 1951 ) -> PResult<'a, L> { 1952 if let token::Interpolated(nt) = &self.token.kind 1953 && let token::NtExpr(e) | token::NtLiteral(e) = &**nt 1954 && matches!(e.kind, ExprKind::Err) 1955 { 1956 let mut err = errors::InvalidInterpolatedExpression { span: self.token.span } 1957 .into_diagnostic(&self.sess.span_diagnostic); 1958 err.downgrade_to_delayed_bug(); 1959 return Err(err); 1960 } 1961 let token = self.token.clone(); 1962 let err = |self_: &Self| { 1963 let msg = format!("unexpected token: {}", super::token_descr(&token)); 1964 self_.struct_span_err(token.span, msg) 1965 }; 1966 // On an error path, eagerly consider a lifetime to be an unclosed character lit 1967 if self.token.is_lifetime() { 1968 let lt = self.expect_lifetime(); 1969 Ok(self.recover_unclosed_char(lt.ident, mk_lit_char, err)) 1970 } else { 1971 Err(err(self)) 1972 } 1973 } 1974 parse_token_lit(&mut self) -> PResult<'a, (token::Lit, Span)>1975 pub(super) fn parse_token_lit(&mut self) -> PResult<'a, (token::Lit, Span)> { 1976 self.parse_opt_token_lit() 1977 .ok_or(()) 1978 .or_else(|()| self.handle_missing_lit(Parser::mk_token_lit_char)) 1979 } 1980 parse_meta_item_lit(&mut self) -> PResult<'a, MetaItemLit>1981 pub(super) fn parse_meta_item_lit(&mut self) -> PResult<'a, MetaItemLit> { 1982 self.parse_opt_meta_item_lit() 1983 .ok_or(()) 1984 .or_else(|()| self.handle_missing_lit(Parser::mk_meta_item_lit_char)) 1985 } 1986 recover_after_dot(&mut self) -> Option<Token>1987 fn recover_after_dot(&mut self) -> Option<Token> { 1988 let mut recovered = None; 1989 if self.token == token::Dot { 1990 // Attempt to recover `.4` as `0.4`. We don't currently have any syntax where 1991 // dot would follow an optional literal, so we do this unconditionally. 1992 recovered = self.look_ahead(1, |next_token| { 1993 if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = 1994 next_token.kind 1995 { 1996 // If this integer looks like a float, then recover as such. 1997 // 1998 // We will never encounter the exponent part of a floating 1999 // point literal here, since there's no use of the exponent 2000 // syntax that also constitutes a valid integer, so we need 2001 // not check for that. 2002 if suffix.map_or(true, |s| s == sym::f32 || s == sym::f64) 2003 && symbol.as_str().chars().all(|c| c.is_numeric() || c == '_') 2004 && self.token.span.hi() == next_token.span.lo() 2005 { 2006 let s = String::from("0.") + symbol.as_str(); 2007 let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix); 2008 return Some(Token::new(kind, self.token.span.to(next_token.span))); 2009 } 2010 } 2011 None 2012 }); 2013 if let Some(token) = &recovered { 2014 self.bump(); 2015 self.sess.emit_err(errors::FloatLiteralRequiresIntegerPart { 2016 span: token.span, 2017 correct: pprust::token_to_string(token).into_owned(), 2018 }); 2019 } 2020 } 2021 2022 recovered 2023 } 2024 2025 /// Matches `lit = true | false | token_lit`. 2026 /// Returns `None` if the next token is not a literal. parse_opt_token_lit(&mut self) -> Option<(token::Lit, Span)>2027 pub(super) fn parse_opt_token_lit(&mut self) -> Option<(token::Lit, Span)> { 2028 let recovered = self.recover_after_dot(); 2029 let token = recovered.as_ref().unwrap_or(&self.token); 2030 let span = token.span; 2031 2032 token::Lit::from_token(token).map(|token_lit| { 2033 self.bump(); 2034 (token_lit, span) 2035 }) 2036 } 2037 2038 /// Matches `lit = true | false | token_lit`. 2039 /// Returns `None` if the next token is not a literal. parse_opt_meta_item_lit(&mut self) -> Option<MetaItemLit>2040 pub(super) fn parse_opt_meta_item_lit(&mut self) -> Option<MetaItemLit> { 2041 let recovered = self.recover_after_dot(); 2042 let token = recovered.as_ref().unwrap_or(&self.token); 2043 match token::Lit::from_token(token) { 2044 Some(lit) => { 2045 match MetaItemLit::from_token_lit(lit, token.span) { 2046 Ok(lit) => { 2047 self.bump(); 2048 Some(lit) 2049 } 2050 Err(err) => { 2051 let span = token.uninterpolated_span(); 2052 self.bump(); 2053 report_lit_error(&self.sess, err, lit, span); 2054 // Pack possible quotes and prefixes from the original literal into 2055 // the error literal's symbol so they can be pretty-printed faithfully. 2056 let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); 2057 let symbol = Symbol::intern(&suffixless_lit.to_string()); 2058 let lit = token::Lit::new(token::Err, symbol, lit.suffix); 2059 Some( 2060 MetaItemLit::from_token_lit(lit, span) 2061 .unwrap_or_else(|_| unreachable!()), 2062 ) 2063 } 2064 } 2065 } 2066 None => None, 2067 } 2068 } 2069 expect_no_tuple_index_suffix(&self, span: Span, suffix: Symbol)2070 pub(super) fn expect_no_tuple_index_suffix(&self, span: Span, suffix: Symbol) { 2071 if [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suffix) { 2072 // #59553: warn instead of reject out of hand to allow the fix to percolate 2073 // through the ecosystem when people fix their macros 2074 self.sess.emit_warning(errors::InvalidLiteralSuffixOnTupleIndex { 2075 span, 2076 suffix, 2077 exception: Some(()), 2078 }); 2079 } else { 2080 self.sess.emit_err(errors::InvalidLiteralSuffixOnTupleIndex { 2081 span, 2082 suffix, 2083 exception: None, 2084 }); 2085 } 2086 } 2087 2088 /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). 2089 /// Keep this in sync with `Token::can_begin_literal_maybe_minus`. parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>>2090 pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> { 2091 maybe_whole_expr!(self); 2092 2093 let lo = self.token.span; 2094 let minus_present = self.eat(&token::BinOp(token::Minus)); 2095 let (token_lit, span) = self.parse_token_lit()?; 2096 let expr = self.mk_expr(span, ExprKind::Lit(token_lit)); 2097 2098 if minus_present { 2099 Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_unary(UnOp::Neg, expr))) 2100 } else { 2101 Ok(expr) 2102 } 2103 } 2104 is_array_like_block(&mut self) -> bool2105 fn is_array_like_block(&mut self) -> bool { 2106 self.look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_))) 2107 && self.look_ahead(2, |t| t == &token::Comma) 2108 && self.look_ahead(3, |t| t.can_begin_expr()) 2109 } 2110 2111 /// Emits a suggestion if it looks like the user meant an array but 2112 /// accidentally used braces, causing the code to be interpreted as a block 2113 /// expression. maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<P<Expr>>2114 fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<P<Expr>> { 2115 let mut snapshot = self.create_snapshot_for_diagnostic(); 2116 match snapshot.parse_expr_array_or_repeat(Delimiter::Brace) { 2117 Ok(arr) => { 2118 self.sess.emit_err(errors::ArrayBracketsInsteadOfSpaces { 2119 span: arr.span, 2120 sub: errors::ArrayBracketsInsteadOfSpacesSugg { 2121 left: lo, 2122 right: snapshot.prev_token.span, 2123 }, 2124 }); 2125 2126 self.restore_snapshot(snapshot); 2127 Some(self.mk_expr_err(arr.span)) 2128 } 2129 Err(e) => { 2130 e.cancel(); 2131 None 2132 } 2133 } 2134 } 2135 suggest_missing_semicolon_before_array( &self, prev_span: Span, open_delim_span: Span, ) -> PResult<'a, ()>2136 fn suggest_missing_semicolon_before_array( 2137 &self, 2138 prev_span: Span, 2139 open_delim_span: Span, 2140 ) -> PResult<'a, ()> { 2141 if !self.may_recover() { 2142 return Ok(()); 2143 } 2144 2145 if self.token.kind == token::Comma { 2146 if !self.sess.source_map().is_multiline(prev_span.until(self.token.span)) { 2147 return Ok(()); 2148 } 2149 let mut snapshot = self.create_snapshot_for_diagnostic(); 2150 snapshot.bump(); 2151 match snapshot.parse_seq_to_before_end( 2152 &token::CloseDelim(Delimiter::Bracket), 2153 SeqSep::trailing_allowed(token::Comma), 2154 |p| p.parse_expr(), 2155 ) { 2156 Ok(_) 2157 // When the close delim is `)`, `token.kind` is expected to be `token::CloseDelim(Delimiter::Parenthesis)`, 2158 // but the actual `token.kind` is `token::CloseDelim(Delimiter::Bracket)`. 2159 // This is because the `token.kind` of the close delim is treated as the same as 2160 // that of the open delim in `TokenTreesReader::parse_token_tree`, even if the delimiters of them are different. 2161 // Therefore, `token.kind` should not be compared here. 2162 if snapshot 2163 .span_to_snippet(snapshot.token.span) 2164 .is_ok_and(|snippet| snippet == "]") => 2165 { 2166 return Err(errors::MissingSemicolonBeforeArray { 2167 open_delim: open_delim_span, 2168 semicolon: prev_span.shrink_to_hi(), 2169 }.into_diagnostic(&self.sess.span_diagnostic)); 2170 } 2171 Ok(_) => (), 2172 Err(err) => err.cancel(), 2173 } 2174 } 2175 Ok(()) 2176 } 2177 2178 /// Parses a block or unsafe block. parse_expr_block( &mut self, opt_label: Option<Label>, lo: Span, blk_mode: BlockCheckMode, ) -> PResult<'a, P<Expr>>2179 pub(super) fn parse_expr_block( 2180 &mut self, 2181 opt_label: Option<Label>, 2182 lo: Span, 2183 blk_mode: BlockCheckMode, 2184 ) -> PResult<'a, P<Expr>> { 2185 if self.may_recover() && self.is_array_like_block() { 2186 if let Some(arr) = self.maybe_suggest_brackets_instead_of_braces(lo) { 2187 return Ok(arr); 2188 } 2189 } 2190 2191 if self.token.is_whole_block() { 2192 self.sess.emit_err(errors::InvalidBlockMacroSegment { 2193 span: self.token.span, 2194 context: lo.to(self.token.span), 2195 wrap: errors::WrapInExplicitBlock { 2196 lo: self.token.span.shrink_to_lo(), 2197 hi: self.token.span.shrink_to_hi(), 2198 }, 2199 }); 2200 } 2201 2202 let (attrs, blk) = self.parse_block_common(lo, blk_mode, true)?; 2203 Ok(self.mk_expr_with_attrs(blk.span, ExprKind::Block(blk, opt_label), attrs)) 2204 } 2205 2206 /// Parse a block which takes no attributes and has no label parse_simple_block(&mut self) -> PResult<'a, P<Expr>>2207 fn parse_simple_block(&mut self) -> PResult<'a, P<Expr>> { 2208 let blk = self.parse_block()?; 2209 Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None))) 2210 } 2211 2212 /// Parses a closure expression (e.g., `move |args| expr`). parse_expr_closure(&mut self) -> PResult<'a, P<Expr>>2213 fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> { 2214 let lo = self.token.span; 2215 2216 let binder = if self.check_keyword(kw::For) { 2217 let lo = self.token.span; 2218 let lifetime_defs = self.parse_late_bound_lifetime_defs()?; 2219 let span = lo.to(self.prev_token.span); 2220 2221 self.sess.gated_spans.gate(sym::closure_lifetime_binder, span); 2222 2223 ClosureBinder::For { span, generic_params: lifetime_defs } 2224 } else { 2225 ClosureBinder::NotPresent 2226 }; 2227 2228 let constness = self.parse_closure_constness(); 2229 2230 let movability = 2231 if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable }; 2232 2233 let asyncness = if self.token.uninterpolated_span().rust_2018() { 2234 self.parse_asyncness(Case::Sensitive) 2235 } else { 2236 Async::No 2237 }; 2238 2239 let capture_clause = self.parse_capture_clause()?; 2240 let (fn_decl, fn_arg_span) = self.parse_fn_block_decl()?; 2241 let decl_hi = self.prev_token.span; 2242 let mut body = match fn_decl.output { 2243 FnRetTy::Default(_) => { 2244 let restrictions = self.restrictions - Restrictions::STMT_EXPR; 2245 self.parse_expr_res(restrictions, None)? 2246 } 2247 _ => { 2248 // If an explicit return type is given, require a block to appear (RFC 968). 2249 let body_lo = self.token.span; 2250 self.parse_expr_block(None, body_lo, BlockCheckMode::Default)? 2251 } 2252 }; 2253 2254 if let Async::Yes { span, .. } = asyncness { 2255 // Feature-gate `async ||` closures. 2256 self.sess.gated_spans.gate(sym::async_closure, span); 2257 } 2258 2259 if self.token.kind == TokenKind::Semi 2260 && matches!(self.token_cursor.stack.last(), Some((_, Delimiter::Parenthesis, _))) 2261 && self.may_recover() 2262 { 2263 // It is likely that the closure body is a block but where the 2264 // braces have been removed. We will recover and eat the next 2265 // statements later in the parsing process. 2266 body = self.mk_expr_err(body.span); 2267 } 2268 2269 let body_span = body.span; 2270 2271 let closure = self.mk_expr( 2272 lo.to(body.span), 2273 ExprKind::Closure(Box::new(ast::Closure { 2274 binder, 2275 capture_clause, 2276 constness, 2277 asyncness, 2278 movability, 2279 fn_decl, 2280 body, 2281 fn_decl_span: lo.to(decl_hi), 2282 fn_arg_span, 2283 })), 2284 ); 2285 2286 // Disable recovery for closure body 2287 let spans = 2288 ClosureSpans { whole_closure: closure.span, closing_pipe: decl_hi, body: body_span }; 2289 self.current_closure = Some(spans); 2290 2291 Ok(closure) 2292 } 2293 2294 /// Parses an optional `move` prefix to a closure-like construct. parse_capture_clause(&mut self) -> PResult<'a, CaptureBy>2295 fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> { 2296 if self.eat_keyword(kw::Move) { 2297 // Check for `move async` and recover 2298 if self.check_keyword(kw::Async) { 2299 let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo); 2300 Err(errors::AsyncMoveOrderIncorrect { span: move_async_span } 2301 .into_diagnostic(&self.sess.span_diagnostic)) 2302 } else { 2303 Ok(CaptureBy::Value) 2304 } 2305 } else { 2306 Ok(CaptureBy::Ref) 2307 } 2308 } 2309 2310 /// Parses the `|arg, arg|` header of a closure. parse_fn_block_decl(&mut self) -> PResult<'a, (P<FnDecl>, Span)>2311 fn parse_fn_block_decl(&mut self) -> PResult<'a, (P<FnDecl>, Span)> { 2312 let arg_start = self.token.span.lo(); 2313 2314 let inputs = if self.eat(&token::OrOr) { 2315 ThinVec::new() 2316 } else { 2317 self.expect(&token::BinOp(token::Or))?; 2318 let args = self 2319 .parse_seq_to_before_tokens( 2320 &[&token::BinOp(token::Or), &token::OrOr], 2321 SeqSep::trailing_allowed(token::Comma), 2322 TokenExpectType::NoExpect, 2323 |p| p.parse_fn_block_param(), 2324 )? 2325 .0; 2326 self.expect_or()?; 2327 args 2328 }; 2329 let arg_span = self.prev_token.span.with_lo(arg_start); 2330 let output = 2331 self.parse_ret_ty(AllowPlus::Yes, RecoverQPath::Yes, RecoverReturnSign::Yes)?; 2332 2333 Ok((P(FnDecl { inputs, output }), arg_span)) 2334 } 2335 2336 /// Parses a parameter in a closure header (e.g., `|arg, arg|`). parse_fn_block_param(&mut self) -> PResult<'a, Param>2337 fn parse_fn_block_param(&mut self) -> PResult<'a, Param> { 2338 let lo = self.token.span; 2339 let attrs = self.parse_outer_attributes()?; 2340 self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { 2341 let pat = this.parse_pat_no_top_alt(Some(Expected::ParameterName))?; 2342 let ty = if this.eat(&token::Colon) { 2343 this.parse_ty()? 2344 } else { 2345 this.mk_ty(this.prev_token.span, TyKind::Infer) 2346 }; 2347 2348 Ok(( 2349 Param { 2350 attrs, 2351 ty, 2352 pat, 2353 span: lo.to(this.prev_token.span), 2354 id: DUMMY_NODE_ID, 2355 is_placeholder: false, 2356 }, 2357 TrailingToken::MaybeComma, 2358 )) 2359 }) 2360 } 2361 2362 /// Parses an `if` expression (`if` token already eaten). parse_expr_if(&mut self) -> PResult<'a, P<Expr>>2363 fn parse_expr_if(&mut self) -> PResult<'a, P<Expr>> { 2364 let lo = self.prev_token.span; 2365 let cond = self.parse_expr_cond()?; 2366 self.parse_if_after_cond(lo, cond) 2367 } 2368 parse_if_after_cond(&mut self, lo: Span, mut cond: P<Expr>) -> PResult<'a, P<Expr>>2369 fn parse_if_after_cond(&mut self, lo: Span, mut cond: P<Expr>) -> PResult<'a, P<Expr>> { 2370 let cond_span = cond.span; 2371 // Tries to interpret `cond` as either a missing expression if it's a block, 2372 // or as an unfinished expression if it's a binop and the RHS is a block. 2373 // We could probably add more recoveries here too... 2374 let mut recover_block_from_condition = |this: &mut Self| { 2375 let block = match &mut cond.kind { 2376 ExprKind::Binary(Spanned { span: binop_span, .. }, _, right) 2377 if let ExprKind::Block(_, None) = right.kind => { 2378 self.sess.emit_err(errors::IfExpressionMissingThenBlock { 2379 if_span: lo, 2380 missing_then_block_sub: 2381 errors::IfExpressionMissingThenBlockSub::UnfinishedCondition(cond_span.shrink_to_lo().to(*binop_span)), 2382 let_else_sub: None, 2383 2384 }); 2385 std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi())) 2386 }, 2387 ExprKind::Block(_, None) => { 2388 self.sess.emit_err(errors::IfExpressionMissingCondition { 2389 if_span: lo.shrink_to_hi(), 2390 block_span: self.sess.source_map().start_point(cond_span), 2391 }); 2392 std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi())) 2393 } 2394 _ => { 2395 return None; 2396 } 2397 }; 2398 if let ExprKind::Block(block, _) = &block.kind { 2399 Some(block.clone()) 2400 } else { 2401 unreachable!() 2402 } 2403 }; 2404 // Parse then block 2405 let thn = if self.token.is_keyword(kw::Else) { 2406 if let Some(block) = recover_block_from_condition(self) { 2407 block 2408 } else { 2409 let let_else_sub = matches!(cond.kind, ExprKind::Let(..)) 2410 .then(|| errors::IfExpressionLetSomeSub { if_span: lo.until(cond_span) }); 2411 2412 self.sess.emit_err(errors::IfExpressionMissingThenBlock { 2413 if_span: lo, 2414 missing_then_block_sub: errors::IfExpressionMissingThenBlockSub::AddThenBlock( 2415 cond_span.shrink_to_hi(), 2416 ), 2417 let_else_sub, 2418 }); 2419 self.mk_block_err(cond_span.shrink_to_hi()) 2420 } 2421 } else { 2422 let attrs = self.parse_outer_attributes()?; // For recovery. 2423 let block = if self.check(&token::OpenDelim(Delimiter::Brace)) { 2424 self.parse_block()? 2425 } else { 2426 if let Some(block) = recover_block_from_condition(self) { 2427 block 2428 } else { 2429 self.error_on_extra_if(&cond)?; 2430 // Parse block, which will always fail, but we can add a nice note to the error 2431 self.parse_block().map_err(|mut err| { 2432 err.span_note( 2433 cond_span, 2434 "the `if` expression is missing a block after this condition", 2435 ); 2436 err 2437 })? 2438 } 2439 }; 2440 self.error_on_if_block_attrs(lo, false, block.span, attrs); 2441 block 2442 }; 2443 let els = if self.eat_keyword(kw::Else) { Some(self.parse_expr_else()?) } else { None }; 2444 Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els))) 2445 } 2446 2447 /// Parses the condition of a `if` or `while` expression. parse_expr_cond(&mut self) -> PResult<'a, P<Expr>>2448 fn parse_expr_cond(&mut self) -> PResult<'a, P<Expr>> { 2449 let cond = 2450 self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)?; 2451 2452 if let ExprKind::Let(..) = cond.kind { 2453 // Remove the last feature gating of a `let` expression since it's stable. 2454 self.sess.gated_spans.ungate_last(sym::let_chains, cond.span); 2455 } 2456 2457 Ok(cond) 2458 } 2459 2460 /// Parses a `let $pat = $expr` pseudo-expression. parse_expr_let(&mut self) -> PResult<'a, P<Expr>>2461 fn parse_expr_let(&mut self) -> PResult<'a, P<Expr>> { 2462 // This is a *approximate* heuristic that detects if `let` chains are 2463 // being parsed in the right position. It's approximate because it 2464 // doesn't deny all invalid `let` expressions, just completely wrong usages. 2465 let not_in_chain = !matches!( 2466 self.prev_token.kind, 2467 TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _) 2468 ); 2469 if !self.restrictions.contains(Restrictions::ALLOW_LET) || not_in_chain { 2470 self.sess.emit_err(errors::ExpectedExpressionFoundLet { span: self.token.span }); 2471 } 2472 2473 self.bump(); // Eat `let` token 2474 let lo = self.prev_token.span; 2475 let pat = self.parse_pat_allow_top_alt( 2476 None, 2477 RecoverComma::Yes, 2478 RecoverColon::Yes, 2479 CommaRecoveryMode::LikelyTuple, 2480 )?; 2481 if self.token == token::EqEq { 2482 self.sess.emit_err(errors::ExpectedEqForLetExpr { 2483 span: self.token.span, 2484 sugg_span: self.token.span, 2485 }); 2486 self.bump(); 2487 } else { 2488 self.expect(&token::Eq)?; 2489 } 2490 let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| { 2491 this.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), None.into()) 2492 })?; 2493 let span = lo.to(expr.span); 2494 self.sess.gated_spans.gate(sym::let_chains, span); 2495 Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span))) 2496 } 2497 2498 /// Parses an `else { ... }` expression (`else` token already eaten). parse_expr_else(&mut self) -> PResult<'a, P<Expr>>2499 fn parse_expr_else(&mut self) -> PResult<'a, P<Expr>> { 2500 let else_span = self.prev_token.span; // `else` 2501 let attrs = self.parse_outer_attributes()?; // For recovery. 2502 let expr = if self.eat_keyword(kw::If) { 2503 self.parse_expr_if()? 2504 } else if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) { 2505 self.parse_simple_block()? 2506 } else { 2507 let snapshot = self.create_snapshot_for_diagnostic(); 2508 let first_tok = super::token_descr(&self.token); 2509 let first_tok_span = self.token.span; 2510 match self.parse_expr() { 2511 Ok(cond) 2512 // If it's not a free-standing expression, and is followed by a block, 2513 // then it's very likely the condition to an `else if`. 2514 if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) 2515 && classify::expr_requires_semi_to_be_stmt(&cond) => 2516 { 2517 self.sess.emit_err(errors::ExpectedElseBlock { 2518 first_tok_span, 2519 first_tok, 2520 else_span, 2521 condition_start: cond.span.shrink_to_lo(), 2522 }); 2523 self.parse_if_after_cond(cond.span.shrink_to_lo(), cond)? 2524 } 2525 Err(e) => { 2526 e.cancel(); 2527 self.restore_snapshot(snapshot); 2528 self.parse_simple_block()? 2529 }, 2530 Ok(_) => { 2531 self.restore_snapshot(snapshot); 2532 self.parse_simple_block()? 2533 }, 2534 } 2535 }; 2536 self.error_on_if_block_attrs(else_span, true, expr.span, attrs); 2537 Ok(expr) 2538 } 2539 error_on_if_block_attrs( &self, ctx_span: Span, is_ctx_else: bool, branch_span: Span, attrs: AttrWrapper, )2540 fn error_on_if_block_attrs( 2541 &self, 2542 ctx_span: Span, 2543 is_ctx_else: bool, 2544 branch_span: Span, 2545 attrs: AttrWrapper, 2546 ) { 2547 if attrs.is_empty() { 2548 return; 2549 } 2550 2551 let attrs: &[ast::Attribute] = &attrs.take_for_recovery(self.sess); 2552 let (attributes, last) = match attrs { 2553 [] => return, 2554 [x0 @ xn] | [x0, .., xn] => (x0.span.to(xn.span), xn.span), 2555 }; 2556 let ctx = if is_ctx_else { "else" } else { "if" }; 2557 self.sess.emit_err(errors::OuterAttributeNotAllowedOnIfElse { 2558 last, 2559 branch_span, 2560 ctx_span, 2561 ctx: ctx.to_string(), 2562 attributes, 2563 }); 2564 } 2565 error_on_extra_if(&mut self, cond: &P<Expr>) -> PResult<'a, ()>2566 fn error_on_extra_if(&mut self, cond: &P<Expr>) -> PResult<'a, ()> { 2567 if let ExprKind::Binary(Spanned { span: binop_span, node: binop}, _, right) = &cond.kind && 2568 let BinOpKind::And = binop && 2569 let ExprKind::If(cond, ..) = &right.kind { 2570 Err(self.sess.create_err(errors::UnexpectedIfWithIf(binop_span.shrink_to_hi().to(cond.span.shrink_to_lo())))) 2571 } else { 2572 Ok(()) 2573 } 2574 } 2575 2576 /// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten). parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>>2577 fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> { 2578 // Record whether we are about to parse `for (`. 2579 // This is used below for recovery in case of `for ( $stuff ) $block` 2580 // in which case we will suggest `for $stuff $block`. 2581 let begin_paren = match self.token.kind { 2582 token::OpenDelim(Delimiter::Parenthesis) => Some(self.token.span), 2583 _ => None, 2584 }; 2585 2586 let pat = self.parse_pat_allow_top_alt( 2587 None, 2588 RecoverComma::Yes, 2589 RecoverColon::Yes, 2590 CommaRecoveryMode::LikelyTuple, 2591 )?; 2592 if !self.eat_keyword(kw::In) { 2593 self.error_missing_in_for_loop(); 2594 } 2595 self.check_for_for_in_in_typo(self.prev_token.span); 2596 let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; 2597 2598 let pat = self.recover_parens_around_for_head(pat, begin_paren); 2599 2600 // Recover from missing expression in `for` loop 2601 if matches!(expr.kind, ExprKind::Block(..)) 2602 && !matches!(self.token.kind, token::OpenDelim(token::Delimiter::Brace)) 2603 && self.may_recover() 2604 { 2605 self.sess 2606 .emit_err(errors::MissingExpressionInForLoop { span: expr.span.shrink_to_lo() }); 2607 let err_expr = self.mk_expr(expr.span, ExprKind::Err); 2608 let block = self.mk_block(thin_vec![], BlockCheckMode::Default, self.prev_token.span); 2609 return Ok(self.mk_expr( 2610 lo.to(self.prev_token.span), 2611 ExprKind::ForLoop(pat, err_expr, block, opt_label), 2612 )); 2613 } 2614 2615 let (attrs, loop_block) = self.parse_inner_attrs_and_block()?; 2616 2617 let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label); 2618 2619 self.recover_loop_else("for", lo)?; 2620 2621 Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs)) 2622 } 2623 2624 /// Recovers from an `else` clause after a loop (`for...else`, `while...else`) recover_loop_else(&mut self, loop_kind: &'static str, loop_kw: Span) -> PResult<'a, ()>2625 fn recover_loop_else(&mut self, loop_kind: &'static str, loop_kw: Span) -> PResult<'a, ()> { 2626 if self.token.is_keyword(kw::Else) && self.may_recover() { 2627 let else_span = self.token.span; 2628 self.bump(); 2629 let else_clause = self.parse_expr_else()?; 2630 self.sess.emit_err(errors::LoopElseNotSupported { 2631 span: else_span.to(else_clause.span), 2632 loop_kind, 2633 loop_kw, 2634 }); 2635 } 2636 Ok(()) 2637 } 2638 error_missing_in_for_loop(&mut self)2639 fn error_missing_in_for_loop(&mut self) { 2640 let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) { 2641 // Possibly using JS syntax (#75311). 2642 let span = self.token.span; 2643 self.bump(); 2644 (span, errors::MissingInInForLoopSub::InNotOf) 2645 } else { 2646 (self.prev_token.span.between(self.token.span), errors::MissingInInForLoopSub::AddIn) 2647 }; 2648 2649 self.sess.emit_err(errors::MissingInInForLoop { span, sub: sub(span) }); 2650 } 2651 2652 /// Parses a `while` or `while let` expression (`while` token already eaten). parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>>2653 fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> { 2654 let cond = self.parse_expr_cond().map_err(|mut err| { 2655 err.span_label(lo, "while parsing the condition of this `while` expression"); 2656 err 2657 })?; 2658 let (attrs, body) = self.parse_inner_attrs_and_block().map_err(|mut err| { 2659 err.span_label(lo, "while parsing the body of this `while` expression"); 2660 err.span_label(cond.span, "this `while` condition successfully parsed"); 2661 err 2662 })?; 2663 2664 self.recover_loop_else("while", lo)?; 2665 2666 Ok(self.mk_expr_with_attrs( 2667 lo.to(self.prev_token.span), 2668 ExprKind::While(cond, body, opt_label), 2669 attrs, 2670 )) 2671 } 2672 2673 /// Parses `loop { ... }` (`loop` token already eaten). parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>>2674 fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> { 2675 let loop_span = self.prev_token.span; 2676 let (attrs, body) = self.parse_inner_attrs_and_block()?; 2677 self.recover_loop_else("loop", lo)?; 2678 Ok(self.mk_expr_with_attrs( 2679 lo.to(self.prev_token.span), 2680 ExprKind::Loop(body, opt_label, loop_span), 2681 attrs, 2682 )) 2683 } 2684 eat_label(&mut self) -> Option<Label>2685 pub(crate) fn eat_label(&mut self) -> Option<Label> { 2686 self.token.lifetime().map(|ident| { 2687 self.bump(); 2688 Label { ident } 2689 }) 2690 } 2691 2692 /// Parses a `match ... { ... }` expression (`match` token already eaten). parse_expr_match(&mut self) -> PResult<'a, P<Expr>>2693 fn parse_expr_match(&mut self) -> PResult<'a, P<Expr>> { 2694 let match_span = self.prev_token.span; 2695 let lo = self.prev_token.span; 2696 let scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; 2697 if let Err(mut e) = self.expect(&token::OpenDelim(Delimiter::Brace)) { 2698 if self.token == token::Semi { 2699 e.span_suggestion_short( 2700 match_span, 2701 "try removing this `match`", 2702 "", 2703 Applicability::MaybeIncorrect, // speculative 2704 ); 2705 } 2706 if self.maybe_recover_unexpected_block_label() { 2707 e.cancel(); 2708 self.bump(); 2709 } else { 2710 return Err(e); 2711 } 2712 } 2713 let attrs = self.parse_inner_attributes()?; 2714 2715 let mut arms = ThinVec::new(); 2716 while self.token != token::CloseDelim(Delimiter::Brace) { 2717 match self.parse_arm() { 2718 Ok(arm) => arms.push(arm), 2719 Err(mut e) => { 2720 // Recover by skipping to the end of the block. 2721 e.emit(); 2722 self.recover_stmt(); 2723 let span = lo.to(self.token.span); 2724 if self.token == token::CloseDelim(Delimiter::Brace) { 2725 self.bump(); 2726 } 2727 return Ok(self.mk_expr_with_attrs( 2728 span, 2729 ExprKind::Match(scrutinee, arms), 2730 attrs, 2731 )); 2732 } 2733 } 2734 } 2735 let hi = self.token.span; 2736 self.bump(); 2737 Ok(self.mk_expr_with_attrs(lo.to(hi), ExprKind::Match(scrutinee, arms), attrs)) 2738 } 2739 2740 /// Attempt to recover from match arm body with statements and no surrounding braces. parse_arm_body_missing_braces( &mut self, first_expr: &P<Expr>, arrow_span: Span, ) -> Option<P<Expr>>2741 fn parse_arm_body_missing_braces( 2742 &mut self, 2743 first_expr: &P<Expr>, 2744 arrow_span: Span, 2745 ) -> Option<P<Expr>> { 2746 if self.token.kind != token::Semi { 2747 return None; 2748 } 2749 let start_snapshot = self.create_snapshot_for_diagnostic(); 2750 let semi_sp = self.token.span; 2751 self.bump(); // `;` 2752 let mut stmts = 2753 vec![self.mk_stmt(first_expr.span, ast::StmtKind::Expr(first_expr.clone()))]; 2754 let err = |this: &Parser<'_>, stmts: Vec<ast::Stmt>| { 2755 let span = stmts[0].span.to(stmts[stmts.len() - 1].span); 2756 2757 this.sess.emit_err(errors::MatchArmBodyWithoutBraces { 2758 statements: span, 2759 arrow: arrow_span, 2760 num_statements: stmts.len(), 2761 sub: if stmts.len() > 1 { 2762 errors::MatchArmBodyWithoutBracesSugg::AddBraces { 2763 left: span.shrink_to_lo(), 2764 right: span.shrink_to_hi(), 2765 } 2766 } else { 2767 errors::MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp } 2768 }, 2769 }); 2770 this.mk_expr_err(span) 2771 }; 2772 // We might have either a `,` -> `;` typo, or a block without braces. We need 2773 // a more subtle parsing strategy. 2774 loop { 2775 if self.token.kind == token::CloseDelim(Delimiter::Brace) { 2776 // We have reached the closing brace of the `match` expression. 2777 return Some(err(self, stmts)); 2778 } 2779 if self.token.kind == token::Comma { 2780 self.restore_snapshot(start_snapshot); 2781 return None; 2782 } 2783 let pre_pat_snapshot = self.create_snapshot_for_diagnostic(); 2784 match self.parse_pat_no_top_alt(None) { 2785 Ok(_pat) => { 2786 if self.token.kind == token::FatArrow { 2787 // Reached arm end. 2788 self.restore_snapshot(pre_pat_snapshot); 2789 return Some(err(self, stmts)); 2790 } 2791 } 2792 Err(err) => { 2793 err.cancel(); 2794 } 2795 } 2796 2797 self.restore_snapshot(pre_pat_snapshot); 2798 match self.parse_stmt_without_recovery(true, ForceCollect::No) { 2799 // Consume statements for as long as possible. 2800 Ok(Some(stmt)) => { 2801 stmts.push(stmt); 2802 } 2803 Ok(None) => { 2804 self.restore_snapshot(start_snapshot); 2805 break; 2806 } 2807 // We couldn't parse either yet another statement missing it's 2808 // enclosing block nor the next arm's pattern or closing brace. 2809 Err(stmt_err) => { 2810 stmt_err.cancel(); 2811 self.restore_snapshot(start_snapshot); 2812 break; 2813 } 2814 } 2815 } 2816 None 2817 } 2818 parse_arm(&mut self) -> PResult<'a, Arm>2819 pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> { 2820 // Used to check the `let_chains` and `if_let_guard` features mostly by scanning 2821 // `&&` tokens. 2822 fn check_let_expr(expr: &Expr) -> (bool, bool) { 2823 match &expr.kind { 2824 ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, lhs, rhs) => { 2825 let lhs_rslt = check_let_expr(lhs); 2826 let rhs_rslt = check_let_expr(rhs); 2827 (lhs_rslt.0 || rhs_rslt.0, false) 2828 } 2829 ExprKind::Let(..) => (true, true), 2830 _ => (false, true), 2831 } 2832 } 2833 let attrs = self.parse_outer_attributes()?; 2834 self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { 2835 let lo = this.token.span; 2836 let pat = this.parse_pat_allow_top_alt( 2837 None, 2838 RecoverComma::Yes, 2839 RecoverColon::Yes, 2840 CommaRecoveryMode::EitherTupleOrPipe, 2841 )?; 2842 let guard = if this.eat_keyword(kw::If) { 2843 let if_span = this.prev_token.span; 2844 let cond = this.parse_expr_res(Restrictions::ALLOW_LET, None)?; 2845 let (has_let_expr, does_not_have_bin_op) = check_let_expr(&cond); 2846 if has_let_expr { 2847 if does_not_have_bin_op { 2848 // Remove the last feature gating of a `let` expression since it's stable. 2849 this.sess.gated_spans.ungate_last(sym::let_chains, cond.span); 2850 } 2851 let span = if_span.to(cond.span); 2852 this.sess.gated_spans.gate(sym::if_let_guard, span); 2853 } 2854 Some(cond) 2855 } else { 2856 None 2857 }; 2858 let arrow_span = this.token.span; 2859 if let Err(mut err) = this.expect(&token::FatArrow) { 2860 // We might have a `=>` -> `=` or `->` typo (issue #89396). 2861 if TokenKind::FatArrow 2862 .similar_tokens() 2863 .is_some_and(|similar_tokens| similar_tokens.contains(&this.token.kind)) 2864 { 2865 err.span_suggestion( 2866 this.token.span, 2867 "try using a fat arrow here", 2868 "=>", 2869 Applicability::MaybeIncorrect, 2870 ); 2871 err.emit(); 2872 this.bump(); 2873 } else if matches!( 2874 (&this.prev_token.kind, &this.token.kind), 2875 (token::DotDotEq, token::Gt) 2876 ) { 2877 // `error_inclusive_range_match_arrow` handles cases like `0..=> {}`, 2878 // so we suppress the error here 2879 err.delay_as_bug(); 2880 this.bump(); 2881 } else { 2882 return Err(err); 2883 } 2884 } 2885 let arm_start_span = this.token.span; 2886 2887 let expr = this.parse_expr_res(Restrictions::STMT_EXPR, None).map_err(|mut err| { 2888 err.span_label(arrow_span, "while parsing the `match` arm starting here"); 2889 err 2890 })?; 2891 2892 let require_comma = classify::expr_requires_semi_to_be_stmt(&expr) 2893 && this.token != token::CloseDelim(Delimiter::Brace); 2894 2895 let hi = this.prev_token.span; 2896 2897 if require_comma { 2898 let sm = this.sess.source_map(); 2899 if let Some(body) = this.parse_arm_body_missing_braces(&expr, arrow_span) { 2900 let span = body.span; 2901 return Ok(( 2902 ast::Arm { 2903 attrs, 2904 pat, 2905 guard, 2906 body, 2907 span, 2908 id: DUMMY_NODE_ID, 2909 is_placeholder: false, 2910 }, 2911 TrailingToken::None, 2912 )); 2913 } 2914 this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)]) 2915 .or_else(|mut err| { 2916 if this.token == token::FatArrow { 2917 if let Ok(expr_lines) = sm.span_to_lines(expr.span) 2918 && let Ok(arm_start_lines) = sm.span_to_lines(arm_start_span) 2919 && arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col 2920 && expr_lines.lines.len() == 2 2921 { 2922 // We check whether there's any trailing code in the parse span, 2923 // if there isn't, we very likely have the following: 2924 // 2925 // X | &Y => "y" 2926 // | -- - missing comma 2927 // | | 2928 // | arrow_span 2929 // X | &X => "x" 2930 // | - ^^ self.token.span 2931 // | | 2932 // | parsed until here as `"y" & X` 2933 err.span_suggestion_short( 2934 arm_start_span.shrink_to_hi(), 2935 "missing a comma here to end this `match` arm", 2936 ",", 2937 Applicability::MachineApplicable, 2938 ); 2939 return Err(err); 2940 } 2941 } else { 2942 // FIXME(compiler-errors): We could also recover `; PAT =>` here 2943 2944 // Try to parse a following `PAT =>`, if successful 2945 // then we should recover. 2946 let mut snapshot = this.create_snapshot_for_diagnostic(); 2947 let pattern_follows = snapshot 2948 .parse_pat_allow_top_alt( 2949 None, 2950 RecoverComma::Yes, 2951 RecoverColon::Yes, 2952 CommaRecoveryMode::EitherTupleOrPipe, 2953 ) 2954 .map_err(|err| err.cancel()) 2955 .is_ok(); 2956 if pattern_follows && snapshot.check(&TokenKind::FatArrow) { 2957 err.cancel(); 2958 this.sess.emit_err(errors::MissingCommaAfterMatchArm { 2959 span: hi.shrink_to_hi(), 2960 }); 2961 return Ok(true); 2962 } 2963 } 2964 err.span_label(arrow_span, "while parsing the `match` arm starting here"); 2965 Err(err) 2966 })?; 2967 } else { 2968 this.eat(&token::Comma); 2969 } 2970 2971 Ok(( 2972 ast::Arm { 2973 attrs, 2974 pat, 2975 guard, 2976 body: expr, 2977 span: lo.to(hi), 2978 id: DUMMY_NODE_ID, 2979 is_placeholder: false, 2980 }, 2981 TrailingToken::None, 2982 )) 2983 }) 2984 } 2985 is_builtin(&self) -> bool2986 pub(crate) fn is_builtin(&self) -> bool { 2987 self.token.is_keyword(kw::Builtin) && self.look_ahead(1, |t| *t == token::Pound) 2988 } 2989 2990 /// Parses a `try {...}` expression (`try` token already eaten). parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>>2991 fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> { 2992 let (attrs, body) = self.parse_inner_attrs_and_block()?; 2993 if self.eat_keyword(kw::Catch) { 2994 Err(errors::CatchAfterTry { span: self.prev_token.span } 2995 .into_diagnostic(&self.sess.span_diagnostic)) 2996 } else { 2997 let span = span_lo.to(body.span); 2998 self.sess.gated_spans.gate(sym::try_blocks, span); 2999 Ok(self.mk_expr_with_attrs(span, ExprKind::TryBlock(body), attrs)) 3000 } 3001 } 3002 is_do_catch_block(&self) -> bool3003 fn is_do_catch_block(&self) -> bool { 3004 self.token.is_keyword(kw::Do) 3005 && self.is_keyword_ahead(1, &[kw::Catch]) 3006 && self.look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Brace)) 3007 && !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) 3008 } 3009 is_do_yeet(&self) -> bool3010 fn is_do_yeet(&self) -> bool { 3011 self.token.is_keyword(kw::Do) && self.is_keyword_ahead(1, &[kw::Yeet]) 3012 } 3013 is_try_block(&self) -> bool3014 fn is_try_block(&self) -> bool { 3015 self.token.is_keyword(kw::Try) 3016 && self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace)) 3017 && self.token.uninterpolated_span().rust_2018() 3018 } 3019 3020 /// Parses an `async move? {...}` expression. parse_async_block(&mut self) -> PResult<'a, P<Expr>>3021 fn parse_async_block(&mut self) -> PResult<'a, P<Expr>> { 3022 let lo = self.token.span; 3023 self.expect_keyword(kw::Async)?; 3024 let capture_clause = self.parse_capture_clause()?; 3025 let (attrs, body) = self.parse_inner_attrs_and_block()?; 3026 let kind = ExprKind::Async(capture_clause, body); 3027 Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs)) 3028 } 3029 is_async_block(&self) -> bool3030 fn is_async_block(&self) -> bool { 3031 self.token.is_keyword(kw::Async) 3032 && (( 3033 // `async move {` 3034 self.is_keyword_ahead(1, &[kw::Move]) 3035 && self.look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Brace)) 3036 ) || ( 3037 // `async {` 3038 self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace)) 3039 )) 3040 } 3041 is_certainly_not_a_block(&self) -> bool3042 fn is_certainly_not_a_block(&self) -> bool { 3043 self.look_ahead(1, |t| t.is_ident()) 3044 && ( 3045 // `{ ident, ` cannot start a block. 3046 self.look_ahead(2, |t| t == &token::Comma) 3047 || self.look_ahead(2, |t| t == &token::Colon) 3048 && ( 3049 // `{ ident: token, ` cannot start a block. 3050 self.look_ahead(4, |t| t == &token::Comma) || 3051 // `{ ident: ` cannot start a block unless it's a type ascription `ident: Type`. 3052 self.look_ahead(3, |t| !t.can_begin_type()) 3053 ) 3054 ) 3055 } 3056 maybe_parse_struct_expr( &mut self, qself: &Option<P<ast::QSelf>>, path: &ast::Path, ) -> Option<PResult<'a, P<Expr>>>3057 fn maybe_parse_struct_expr( 3058 &mut self, 3059 qself: &Option<P<ast::QSelf>>, 3060 path: &ast::Path, 3061 ) -> Option<PResult<'a, P<Expr>>> { 3062 let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL); 3063 if struct_allowed || self.is_certainly_not_a_block() { 3064 if let Err(err) = self.expect(&token::OpenDelim(Delimiter::Brace)) { 3065 return Some(Err(err)); 3066 } 3067 let expr = self.parse_expr_struct(qself.clone(), path.clone(), true); 3068 if let (Ok(expr), false) = (&expr, struct_allowed) { 3069 // This is a struct literal, but we don't can't accept them here. 3070 self.sess.emit_err(errors::StructLiteralNotAllowedHere { 3071 span: expr.span, 3072 sub: errors::StructLiteralNotAllowedHereSugg { 3073 left: path.span.shrink_to_lo(), 3074 right: expr.span.shrink_to_hi(), 3075 }, 3076 }); 3077 } 3078 return Some(expr); 3079 } 3080 None 3081 } 3082 parse_struct_fields( &mut self, pth: ast::Path, recover: bool, close_delim: Delimiter, ) -> PResult<'a, (ThinVec<ExprField>, ast::StructRest, bool)>3083 pub(super) fn parse_struct_fields( 3084 &mut self, 3085 pth: ast::Path, 3086 recover: bool, 3087 close_delim: Delimiter, 3088 ) -> PResult<'a, (ThinVec<ExprField>, ast::StructRest, bool)> { 3089 let mut fields = ThinVec::new(); 3090 let mut base = ast::StructRest::None; 3091 let mut recover_async = false; 3092 3093 let mut async_block_err = |e: &mut Diagnostic, span: Span| { 3094 recover_async = true; 3095 errors::AsyncBlockIn2015 { span }.add_to_diagnostic(e); 3096 errors::HelpUseLatestEdition::new().add_to_diagnostic(e); 3097 }; 3098 3099 while self.token != token::CloseDelim(close_delim) { 3100 if self.eat(&token::DotDot) || self.recover_struct_field_dots(close_delim) { 3101 let exp_span = self.prev_token.span; 3102 // We permit `.. }` on the left-hand side of a destructuring assignment. 3103 if self.check(&token::CloseDelim(close_delim)) { 3104 base = ast::StructRest::Rest(self.prev_token.span.shrink_to_hi()); 3105 break; 3106 } 3107 match self.parse_expr() { 3108 Ok(e) => base = ast::StructRest::Base(e), 3109 Err(mut e) if recover => { 3110 e.emit(); 3111 self.recover_stmt(); 3112 } 3113 Err(e) => return Err(e), 3114 } 3115 self.recover_struct_comma_after_dotdot(exp_span); 3116 break; 3117 } 3118 3119 let recovery_field = self.find_struct_error_after_field_looking_code(); 3120 let parsed_field = match self.parse_expr_field() { 3121 Ok(f) => Some(f), 3122 Err(mut e) => { 3123 if pth == kw::Async { 3124 async_block_err(&mut e, pth.span); 3125 } else { 3126 e.span_label(pth.span, "while parsing this struct"); 3127 } 3128 3129 if !recover { 3130 return Err(e); 3131 } 3132 3133 e.emit(); 3134 3135 // If the next token is a comma, then try to parse 3136 // what comes next as additional fields, rather than 3137 // bailing out until next `}`. 3138 if self.token != token::Comma { 3139 self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore); 3140 if self.token != token::Comma { 3141 break; 3142 } 3143 } 3144 3145 None 3146 } 3147 }; 3148 3149 let is_shorthand = parsed_field.as_ref().is_some_and(|f| f.is_shorthand); 3150 // A shorthand field can be turned into a full field with `:`. 3151 // We should point this out. 3152 self.check_or_expected(!is_shorthand, TokenType::Token(token::Colon)); 3153 3154 match self.expect_one_of(&[token::Comma], &[token::CloseDelim(close_delim)]) { 3155 Ok(_) => { 3156 if let Some(f) = parsed_field.or(recovery_field) { 3157 // Only include the field if there's no parse error for the field name. 3158 fields.push(f); 3159 } 3160 } 3161 Err(mut e) => { 3162 if pth == kw::Async { 3163 async_block_err(&mut e, pth.span); 3164 } else { 3165 e.span_label(pth.span, "while parsing this struct"); 3166 if let Some(f) = recovery_field { 3167 fields.push(f); 3168 e.span_suggestion( 3169 self.prev_token.span.shrink_to_hi(), 3170 "try adding a comma", 3171 ",", 3172 Applicability::MachineApplicable, 3173 ); 3174 } else if is_shorthand 3175 && (AssocOp::from_token(&self.token).is_some() 3176 || matches!(&self.token.kind, token::OpenDelim(_)) 3177 || self.token.kind == token::Dot) 3178 { 3179 // Looks like they tried to write a shorthand, complex expression. 3180 let ident = parsed_field.expect("is_shorthand implies Some").ident; 3181 e.span_suggestion( 3182 ident.span.shrink_to_lo(), 3183 "try naming a field", 3184 &format!("{ident}: "), 3185 Applicability::HasPlaceholders, 3186 ); 3187 } 3188 } 3189 if !recover { 3190 return Err(e); 3191 } 3192 e.emit(); 3193 self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore); 3194 self.eat(&token::Comma); 3195 } 3196 } 3197 } 3198 Ok((fields, base, recover_async)) 3199 } 3200 3201 /// Precondition: already parsed the '{'. parse_expr_struct( &mut self, qself: Option<P<ast::QSelf>>, pth: ast::Path, recover: bool, ) -> PResult<'a, P<Expr>>3202 pub(super) fn parse_expr_struct( 3203 &mut self, 3204 qself: Option<P<ast::QSelf>>, 3205 pth: ast::Path, 3206 recover: bool, 3207 ) -> PResult<'a, P<Expr>> { 3208 let lo = pth.span; 3209 let (fields, base, recover_async) = 3210 self.parse_struct_fields(pth.clone(), recover, Delimiter::Brace)?; 3211 let span = lo.to(self.token.span); 3212 self.expect(&token::CloseDelim(Delimiter::Brace))?; 3213 let expr = if recover_async { 3214 ExprKind::Err 3215 } else { 3216 ExprKind::Struct(P(ast::StructExpr { qself, path: pth, fields, rest: base })) 3217 }; 3218 Ok(self.mk_expr(span, expr)) 3219 } 3220 3221 /// Use in case of error after field-looking code: `S { foo: () with a }`. find_struct_error_after_field_looking_code(&self) -> Option<ExprField>3222 fn find_struct_error_after_field_looking_code(&self) -> Option<ExprField> { 3223 match self.token.ident() { 3224 Some((ident, is_raw)) 3225 if (is_raw || !ident.is_reserved()) 3226 && self.look_ahead(1, |t| *t == token::Colon) => 3227 { 3228 Some(ast::ExprField { 3229 ident, 3230 span: self.token.span, 3231 expr: self.mk_expr_err(self.token.span), 3232 is_shorthand: false, 3233 attrs: AttrVec::new(), 3234 id: DUMMY_NODE_ID, 3235 is_placeholder: false, 3236 }) 3237 } 3238 _ => None, 3239 } 3240 } 3241 recover_struct_comma_after_dotdot(&mut self, span: Span)3242 fn recover_struct_comma_after_dotdot(&mut self, span: Span) { 3243 if self.token != token::Comma { 3244 return; 3245 } 3246 self.sess.emit_err(errors::CommaAfterBaseStruct { 3247 span: span.to(self.prev_token.span), 3248 comma: self.token.span, 3249 }); 3250 self.recover_stmt(); 3251 } 3252 recover_struct_field_dots(&mut self, close_delim: Delimiter) -> bool3253 fn recover_struct_field_dots(&mut self, close_delim: Delimiter) -> bool { 3254 if !self.look_ahead(1, |t| *t == token::CloseDelim(close_delim)) 3255 && self.eat(&token::DotDotDot) 3256 { 3257 // recover from typo of `...`, suggest `..` 3258 let span = self.prev_token.span; 3259 self.sess.emit_err(errors::MissingDotDot { token_span: span, sugg_span: span }); 3260 return true; 3261 } 3262 false 3263 } 3264 3265 /// Converts an ident into 'label and emits an "expected a label, found an identifier" error. recover_ident_into_label(&mut self, ident: Ident) -> Label3266 fn recover_ident_into_label(&mut self, ident: Ident) -> Label { 3267 // Convert `label` -> `'label`, 3268 // so that nameres doesn't complain about non-existing label 3269 let label = format!("'{}", ident.name); 3270 let ident = Ident { name: Symbol::intern(&label), span: ident.span }; 3271 3272 self.sess.emit_err(errors::ExpectedLabelFoundIdent { 3273 span: ident.span, 3274 start: ident.span.shrink_to_lo(), 3275 }); 3276 3277 Label { ident } 3278 } 3279 3280 /// Parses `ident (COLON expr)?`. parse_expr_field(&mut self) -> PResult<'a, ExprField>3281 fn parse_expr_field(&mut self) -> PResult<'a, ExprField> { 3282 let attrs = self.parse_outer_attributes()?; 3283 self.recover_diff_marker(); 3284 self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { 3285 let lo = this.token.span; 3286 3287 // Check if a colon exists one ahead. This means we're parsing a fieldname. 3288 let is_shorthand = !this.look_ahead(1, |t| t == &token::Colon || t == &token::Eq); 3289 let (ident, expr) = if is_shorthand { 3290 // Mimic `x: x` for the `x` field shorthand. 3291 let ident = this.parse_ident_common(false)?; 3292 let path = ast::Path::from_ident(ident); 3293 (ident, this.mk_expr(ident.span, ExprKind::Path(None, path))) 3294 } else { 3295 let ident = this.parse_field_name()?; 3296 this.error_on_eq_field_init(ident); 3297 this.bump(); // `:` 3298 (ident, this.parse_expr()?) 3299 }; 3300 3301 Ok(( 3302 ast::ExprField { 3303 ident, 3304 span: lo.to(expr.span), 3305 expr, 3306 is_shorthand, 3307 attrs, 3308 id: DUMMY_NODE_ID, 3309 is_placeholder: false, 3310 }, 3311 TrailingToken::MaybeComma, 3312 )) 3313 }) 3314 } 3315 3316 /// Check for `=`. This means the source incorrectly attempts to 3317 /// initialize a field with an eq rather than a colon. error_on_eq_field_init(&self, field_name: Ident)3318 fn error_on_eq_field_init(&self, field_name: Ident) { 3319 if self.token != token::Eq { 3320 return; 3321 } 3322 3323 self.sess.emit_err(errors::EqFieldInit { 3324 span: self.token.span, 3325 eq: field_name.span.shrink_to_hi().to(self.token.span), 3326 }); 3327 } 3328 err_dotdotdot_syntax(&self, span: Span)3329 fn err_dotdotdot_syntax(&self, span: Span) { 3330 self.sess.emit_err(errors::DotDotDot { span }); 3331 } 3332 err_larrow_operator(&self, span: Span)3333 fn err_larrow_operator(&self, span: Span) { 3334 self.sess.emit_err(errors::LeftArrowOperator { span }); 3335 } 3336 mk_assign_op(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind3337 fn mk_assign_op(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind { 3338 ExprKind::AssignOp(binop, lhs, rhs) 3339 } 3340 mk_range( &mut self, start: Option<P<Expr>>, end: Option<P<Expr>>, limits: RangeLimits, ) -> ExprKind3341 fn mk_range( 3342 &mut self, 3343 start: Option<P<Expr>>, 3344 end: Option<P<Expr>>, 3345 limits: RangeLimits, 3346 ) -> ExprKind { 3347 if end.is_none() && limits == RangeLimits::Closed { 3348 self.inclusive_range_with_incorrect_end(); 3349 ExprKind::Err 3350 } else { 3351 ExprKind::Range(start, end, limits) 3352 } 3353 } 3354 mk_unary(&self, unop: UnOp, expr: P<Expr>) -> ExprKind3355 fn mk_unary(&self, unop: UnOp, expr: P<Expr>) -> ExprKind { 3356 ExprKind::Unary(unop, expr) 3357 } 3358 mk_binary(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind3359 fn mk_binary(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind { 3360 ExprKind::Binary(binop, lhs, rhs) 3361 } 3362 mk_index(&self, expr: P<Expr>, idx: P<Expr>) -> ExprKind3363 fn mk_index(&self, expr: P<Expr>, idx: P<Expr>) -> ExprKind { 3364 ExprKind::Index(expr, idx) 3365 } 3366 mk_call(&self, f: P<Expr>, args: ThinVec<P<Expr>>) -> ExprKind3367 fn mk_call(&self, f: P<Expr>, args: ThinVec<P<Expr>>) -> ExprKind { 3368 ExprKind::Call(f, args) 3369 } 3370 mk_await_expr(&mut self, self_arg: P<Expr>, lo: Span) -> P<Expr>3371 fn mk_await_expr(&mut self, self_arg: P<Expr>, lo: Span) -> P<Expr> { 3372 let span = lo.to(self.prev_token.span); 3373 let await_expr = self.mk_expr(span, ExprKind::Await(self_arg, self.prev_token.span)); 3374 self.recover_from_await_method_call(); 3375 await_expr 3376 } 3377 mk_expr_with_attrs(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr>3378 pub(crate) fn mk_expr_with_attrs(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> { 3379 P(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None }) 3380 } 3381 mk_expr(&self, span: Span, kind: ExprKind) -> P<Expr>3382 pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> P<Expr> { 3383 P(Expr { kind, span, attrs: AttrVec::new(), id: DUMMY_NODE_ID, tokens: None }) 3384 } 3385 mk_expr_err(&self, span: Span) -> P<Expr>3386 pub(super) fn mk_expr_err(&self, span: Span) -> P<Expr> { 3387 self.mk_expr(span, ExprKind::Err) 3388 } 3389 3390 /// Create expression span ensuring the span of the parent node 3391 /// is larger than the span of lhs and rhs, including the attributes. mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) -> Span3392 fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) -> Span { 3393 lhs.attrs 3394 .iter() 3395 .find(|a| a.style == AttrStyle::Outer) 3396 .map_or(lhs_span, |a| a.span) 3397 .to(rhs_span) 3398 } 3399 collect_tokens_for_expr( &mut self, attrs: AttrWrapper, f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, P<Expr>>, ) -> PResult<'a, P<Expr>>3400 fn collect_tokens_for_expr( 3401 &mut self, 3402 attrs: AttrWrapper, 3403 f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, P<Expr>>, 3404 ) -> PResult<'a, P<Expr>> { 3405 self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { 3406 let res = f(this, attrs)?; 3407 let trailing = if this.restrictions.contains(Restrictions::STMT_EXPR) 3408 && this.token.kind == token::Semi 3409 { 3410 TrailingToken::Semi 3411 } else if this.token.kind == token::Gt { 3412 TrailingToken::Gt 3413 } else { 3414 // FIXME - pass this through from the place where we know 3415 // we need a comma, rather than assuming that `#[attr] expr,` 3416 // always captures a trailing comma 3417 TrailingToken::MaybeComma 3418 }; 3419 Ok((res, trailing)) 3420 }) 3421 } 3422 } 3423