From 9918693037dce8aa4bb6f08741b6812923486c18 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 19 Jun 2024 11:26:03 +0200 Subject: Merging upstream version 1.76.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_parse/src/parser/expr.rs | 614 ++++++++++++++++++++------------ 1 file changed, 396 insertions(+), 218 deletions(-) (limited to 'compiler/rustc_parse/src/parser/expr.rs') diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 235b28b6e..cd3e8b92f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1,3 +1,4 @@ +// ignore-tidy-filelength use super::diagnostics::SnapshotParser; use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; @@ -9,7 +10,7 @@ use super::{ use crate::errors; use crate::maybe_recover_from_interpolated_ty_qpath; use ast::mut_visit::{noop_visit_expr, MutVisitor}; -use ast::{GenBlockKind, Path, PathSegment}; +use ast::{CoroutineKind, GenBlockKind, Pat, Path, PathSegment}; use core::mem; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; @@ -20,7 +21,7 @@ use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity}; use rustc_ast::visit::Visitor; use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, UnOp, DUMMY_NODE_ID}; use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind}; -use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; +use rustc_ast::{Arm, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -46,7 +47,7 @@ use thin_vec::{thin_vec, ThinVec}; macro_rules! maybe_whole_expr { ($p:expr) => { if let token::Interpolated(nt) = &$p.token.kind { - match &**nt { + match &nt.0 { token::NtExpr(e) | token::NtLiteral(e) => { let e = e.clone(); $p.bump(); @@ -1060,7 +1061,7 @@ impl<'a> Parser<'a> { match &*components { // 1e2 [IdentLike(i)] => { - DestructuredFloat::Single(Symbol::intern(&i), span) + DestructuredFloat::Single(Symbol::intern(i), span) } // 1. [IdentLike(i), Punct('.')] => { @@ -1072,7 +1073,7 @@ impl<'a> Parser<'a> { } else { (span, span) }; - let symbol = Symbol::intern(&i); + let symbol = Symbol::intern(i); DestructuredFloat::TrailingDot(symbol, ident_span, dot_span) } // 1.2 | 1.2e3 @@ -1088,8 +1089,8 @@ impl<'a> Parser<'a> { } else { (span, span, span) }; - let symbol1 = Symbol::intern(&i1); - let symbol2 = Symbol::intern(&i2); + let symbol1 = Symbol::intern(i1); + let symbol2 = Symbol::intern(i2); DestructuredFloat::MiddleDot(symbol1, ident1_span, dot_span, symbol2, ident2_span) } // 1e+ | 1e- (recovered) @@ -1268,7 +1269,7 @@ impl<'a> Parser<'a> { .collect(), }, } - .into_diagnostic(&self.sess.span_diagnostic); + .into_diagnostic(self.dcx()); replacement_err.emit(); let old_err = mem::replace(err, replacement_err); @@ -1439,22 +1440,25 @@ impl<'a> Parser<'a> { } else if this.eat_keyword(kw::Underscore) { Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore)) } else if this.token.uninterpolated_span().at_least_rust_2018() { - // `Span:.at_least_rust_2018()` is somewhat expensive; don't get it repeatedly. - if this.check_keyword(kw::Async) { - if this.is_gen_block(kw::Async) { - // Check for `async {` and `async move {`. + // `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly. + if this.token.uninterpolated_span().at_least_rust_2024() + // check for `gen {}` and `gen move {}` + // or `async gen {}` and `async gen move {}` + && (this.is_gen_block(kw::Gen, 0) + || (this.check_keyword(kw::Async) && this.is_gen_block(kw::Gen, 1))) + { + // FIXME: (async) gen closures aren't yet parsed. + this.parse_gen_block() + } else if this.check_keyword(kw::Async) { + // FIXME(gen_blocks): Parse `gen async` and suggest swap + if this.is_gen_block(kw::Async, 0) { + // Check for `async {` and `async move {`, this.parse_gen_block() } else { this.parse_expr_closure() } - } else if this.eat_keyword(kw::Await) { + } else if this.eat_keyword_noexpect(kw::Await) { this.recover_incorrect_await_syntax(lo, this.prev_token.span) - } else if this.token.uninterpolated_span().at_least_rust_2024() { - if this.is_gen_block(kw::Gen) { - this.parse_gen_block() - } else { - this.parse_expr_lit() - } } else { this.parse_expr_lit() } @@ -1689,8 +1693,7 @@ impl<'a> Parser<'a> { mk_lit_char: impl FnOnce(Symbol, Span) -> L, err: impl FnOnce(&Self) -> DiagnosticBuilder<'a, ErrorGuaranteed>, ) -> L { - if let Some(mut diag) = - self.sess.span_diagnostic.steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar) + if let Some(mut diag) = self.dcx().steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar) { diag.span_suggestion_verbose( lifetime.span.shrink_to_hi(), @@ -1880,8 +1883,8 @@ impl<'a> Parser<'a> { self.bump(); // `#` let Some((ident, false)) = self.token.ident() else { - let err = errors::ExpectedBuiltinIdent { span: self.token.span } - .into_diagnostic(&self.sess.span_diagnostic); + let err = + errors::ExpectedBuiltinIdent { span: self.token.span }.into_diagnostic(self.dcx()); return Err(err); }; self.sess.gated_spans.gate(sym::builtin_syntax, ident.span); @@ -1892,7 +1895,7 @@ impl<'a> Parser<'a> { Ok(res) } else { let err = errors::UnknownBuiltinConstruct { span: lo.to(ident.span), name: ident.name } - .into_diagnostic(&self.sess.span_diagnostic); + .into_diagnostic(self.dcx()); return Err(err); }; self.expect(&TokenKind::CloseDelim(Delimiter::Parenthesis))?; @@ -1952,11 +1955,11 @@ impl<'a> Parser<'a> { mk_lit_char: impl FnOnce(Symbol, Span) -> L, ) -> PResult<'a, L> { if let token::Interpolated(nt) = &self.token.kind - && let token::NtExpr(e) | token::NtLiteral(e) = &**nt + && let token::NtExpr(e) | token::NtLiteral(e) = &nt.0 && matches!(e.kind, ExprKind::Err) { let mut err = errors::InvalidInterpolatedExpression { span: self.token.span } - .into_diagnostic(&self.sess.span_diagnostic); + .into_diagnostic(self.dcx()); err.downgrade_to_delayed_bug(); return Err(err); } @@ -2052,7 +2055,7 @@ impl<'a> Parser<'a> { Err(err) => { let span = token.uninterpolated_span(); self.bump(); - report_lit_error(&self.sess, err, lit, span); + report_lit_error(self.sess, err, lit, span); // Pack possible quotes and prefixes from the original literal into // the error literal's symbol so they can be pretty-printed faithfully. let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); @@ -2168,7 +2171,7 @@ impl<'a> Parser<'a> { return Err(errors::MissingSemicolonBeforeArray { open_delim: open_delim_span, semicolon: prev_span.shrink_to_hi(), - }.into_diagnostic(&self.sess.span_diagnostic)); + }.into_diagnostic(self.dcx())); } Ok(_) => (), Err(err) => err.cancel(), @@ -2233,10 +2236,10 @@ impl<'a> Parser<'a> { let movability = if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable }; - let asyncness = if self.token.uninterpolated_span().at_least_rust_2018() { - self.parse_asyncness(Case::Sensitive) + let coroutine_kind = if self.token.uninterpolated_span().at_least_rust_2018() { + self.parse_coroutine_kind(Case::Sensitive) } else { - Async::No + None }; let capture_clause = self.parse_capture_clause()?; @@ -2260,13 +2263,21 @@ impl<'a> Parser<'a> { } }; - if let Async::Yes { span, .. } = asyncness { - // Feature-gate `async ||` closures. - self.sess.gated_spans.gate(sym::async_closure, span); + match coroutine_kind { + Some(CoroutineKind::Async { span, .. }) => { + // Feature-gate `async ||` closures. + self.sess.gated_spans.gate(sym::async_closure, span); + } + Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => { + // Feature-gate `gen ||` and `async gen ||` closures. + // FIXME(gen_blocks): This perhaps should be a different gate. + self.sess.gated_spans.gate(sym::gen_blocks, span); + } + None => {} } if self.token.kind == TokenKind::Semi - && matches!(self.token_cursor.stack.last(), Some((_, Delimiter::Parenthesis, _))) + && matches!(self.token_cursor.stack.last(), Some((.., Delimiter::Parenthesis))) && self.may_recover() { // It is likely that the closure body is a block but where the @@ -2283,7 +2294,7 @@ impl<'a> Parser<'a> { binder, capture_clause, constness, - asyncness, + coroutine_kind, movability, fn_decl, body, @@ -2308,7 +2319,7 @@ impl<'a> Parser<'a> { if self.check_keyword(kw::Async) { let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo); Err(errors::AsyncMoveOrderIncorrect { span: move_async_span } - .into_diagnostic(&self.sess.span_diagnostic)) + .into_diagnostic(self.dcx())) } else { Ok(CaptureBy::Value { move_kw: move_kw_span }) } @@ -2477,7 +2488,7 @@ impl<'a> Parser<'a> { let mut cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)?; - CondChecker { parser: self, forbid_let_reason: None }.visit_expr(&mut cond); + CondChecker::new(self).visit_expr(&mut cond); if let ExprKind::Let(_, _, _, None) = cond.kind { // Remove the last feature gating of a `let` expression since it's stable. @@ -2493,10 +2504,12 @@ impl<'a> Parser<'a> { let err = errors::ExpectedExpressionFoundLet { span: self.token.span, reason: ForbiddenLetReason::OtherForbidden, + missing_let: None, + comparison: None, }; if self.prev_token.kind == token::BinOp(token::Or) { // This was part of a closure, the that part of the parser recover. - return Err(err.into_diagnostic(&self.sess.span_diagnostic)); + return Err(err.into_diagnostic(self.dcx())); } else { Some(self.sess.emit_err(err)) } @@ -2606,30 +2619,72 @@ impl<'a> Parser<'a> { } } - /// Parses `for in ` (`for` token already eaten). - fn parse_expr_for(&mut self, opt_label: Option