diff options
| author | The rustc-josh-sync Cronjob Bot <github-actions@github.com> | 2025-08-28 04:13:43 +0000 |
|---|---|---|
| committer | The rustc-josh-sync Cronjob Bot <github-actions@github.com> | 2025-08-28 04:13:43 +0000 |
| commit | e36d827a4ef52eb0db1b8be7e6972a65730b392b (patch) | |
| tree | 33ef7d92c09234e6a3928476d1954e528c327a10 /compiler/rustc_parse/src/parser | |
| parent | 202eb0b375d1e5cfcf19a51f5a6b40d34d5fc0d1 (diff) | |
| parent | d36f964125163c2e698de5559efefb8217b8b7f0 (diff) | |
| download | rust-e36d827a4ef52eb0db1b8be7e6972a65730b392b.tar.gz rust-e36d827a4ef52eb0db1b8be7e6972a65730b392b.zip | |
Merge ref 'd36f96412516' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh. Upstream ref: d36f964125163c2e698de5559efefb8217b8b7f0 Filtered ref: 92461731ae79cfe5044e4826160665b77c0363a2 This merge was created using https://github.com/rust-lang/josh-sync.
Diffstat (limited to 'compiler/rustc_parse/src/parser')
| -rw-r--r-- | compiler/rustc_parse/src/parser/asm.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/attr.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/cfg_select.rs | 30 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 130 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 234 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/generics.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 169 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/mod.rs | 129 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/nonterminal.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 57 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/path.rs | 25 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/stmt.rs | 33 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/tests.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/token_type.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/ty.rs | 240 |
15 files changed, 632 insertions, 471 deletions
diff --git a/compiler/rustc_parse/src/parser/asm.rs b/compiler/rustc_parse/src/parser/asm.rs index d4d0612a317..41c3b0f0b67 100644 --- a/compiler/rustc_parse/src/parser/asm.rs +++ b/compiler/rustc_parse/src/parser/asm.rs @@ -1,4 +1,3 @@ -use rustc_ast::ptr::P; use rustc_ast::{self as ast, AsmMacro}; use rustc_span::{Span, Symbol, kw}; @@ -14,7 +13,7 @@ pub struct AsmArg { } pub enum AsmArgKind { - Template(P<ast::Expr>), + Template(Box<ast::Expr>), Operand(Option<Symbol>, ast::InlineAsmOperand), Options(Vec<AsmOption>), ClobberAbi(Vec<(Symbol, Span)>), diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 41d3889c448..acd338156ce 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -11,6 +11,7 @@ use tracing::debug; use super::{ AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle, Trailing, UsePreAttrPos, }; +use crate::parser::FnContext; use crate::{errors, exp, fluent_generated as fluent}; // Public for rustfmt usage @@ -200,7 +201,7 @@ impl<'a> Parser<'a> { AttrWrapper::empty(), true, false, - FnParseMode { req_name: |_| true, req_body: true }, + FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: true }, ForceCollect::No, ) { Ok(Some(item)) => { @@ -398,7 +399,7 @@ impl<'a> Parser<'a> { } /// Matches `COMMASEP(meta_item_inner)`. - pub(crate) fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec<ast::MetaItemInner>> { + pub fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec<ast::MetaItemInner>> { // Presumably, the majority of the time there will only be one attr. let mut nmis = ThinVec::with_capacity(1); while self.token != token::Eof { diff --git a/compiler/rustc_parse/src/parser/cfg_select.rs b/compiler/rustc_parse/src/parser/cfg_select.rs index 2c6fb224d70..08a71db4de8 100644 --- a/compiler/rustc_parse/src/parser/cfg_select.rs +++ b/compiler/rustc_parse/src/parser/cfg_select.rs @@ -1,11 +1,12 @@ use rustc_ast::token::Token; use rustc_ast::tokenstream::{TokenStream, TokenTree}; +use rustc_ast::util::classify; use rustc_ast::{MetaItemInner, token}; use rustc_errors::PResult; use rustc_span::Span; use crate::exp; -use crate::parser::Parser; +use crate::parser::{AttrWrapper, ForceCollect, Parser, Restrictions, Trailing, UsePreAttrPos}; pub enum CfgSelectPredicate { Cfg(MetaItemInner), @@ -23,19 +24,26 @@ pub struct CfgSelectBranches { pub unreachable: Vec<(CfgSelectPredicate, TokenStream, Span)>, } -/// Parses a `TokenTree` that must be of the form `{ /* ... */ }`, and returns a `TokenStream` where -/// the surrounding braces are stripped. +/// Parses a `TokenTree` consisting either of `{ /* ... */ }` (and strip the braces) or an +/// expression followed by a comma (and strip the comma). fn parse_token_tree<'a>(p: &mut Parser<'a>) -> PResult<'a, TokenStream> { - // Generate an error if the `=>` is not followed by `{`. - if p.token != token::OpenBrace { - p.expect(exp!(OpenBrace))?; + if p.token == token::OpenBrace { + // Strip the outer '{' and '}'. + match p.parse_token_tree() { + TokenTree::Token(..) => unreachable!("because of the expect above"), + TokenTree::Delimited(.., tts) => return Ok(tts), + } } - - // Strip the outer '{' and '}'. - match p.parse_token_tree() { - TokenTree::Token(..) => unreachable!("because of the expect above"), - TokenTree::Delimited(.., tts) => Ok(tts), + let expr = p.collect_tokens(None, AttrWrapper::empty(), ForceCollect::Yes, |p, _| { + p.parse_expr_res(Restrictions::STMT_EXPR, AttrWrapper::empty()) + .map(|(expr, _)| (expr, Trailing::No, UsePreAttrPos::No)) + })?; + if !classify::expr_is_complete(&expr) && p.token != token::CloseBrace && p.token != token::Eof { + p.expect(exp!(Comma))?; + } else { + let _ = p.eat(exp!(Comma)); } + Ok(TokenStream::from_ast(&expr)) } pub fn parse_cfg_select<'a>(p: &mut Parser<'a>) -> PResult<'a, CfgSelectBranches> { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index e0f810d8c1e..a28af7833c3 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -3,7 +3,6 @@ use std::ops::{Deref, DerefMut}; use ast::token::IdentIsRaw; use rustc_ast as ast; -use rustc_ast::ptr::P; use rustc_ast::token::{self, Lit, LitKind, Token, TokenKind}; use rustc_ast::util::parser::AssocOp; use rustc_ast::{ @@ -45,12 +44,13 @@ use crate::errors::{ UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType, }; +use crate::parser::FnContext; use crate::parser::attr::InnerAttrPolicy; use crate::{exp, fluent_generated as fluent}; /// Creates a placeholder argument. pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param { - let pat = P(Pat { + let pat = Box::new(Pat { id: ast::DUMMY_NODE_ID, kind: PatKind::Ident(BindingMode::NONE, ident, None), span: ident.span, @@ -62,23 +62,23 @@ pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param { id: ast::DUMMY_NODE_ID, pat, span: ident.span, - ty: P(ty), + ty: Box::new(ty), is_placeholder: false, } } pub(super) trait RecoverQPath: Sized + 'static { const PATH_STYLE: PathStyle = PathStyle::Expr; - fn to_ty(&self) -> Option<P<Ty>>; - fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self; + fn to_ty(&self) -> Option<Box<Ty>>; + fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self; } impl RecoverQPath for Ty { const PATH_STYLE: PathStyle = PathStyle::Type; - fn to_ty(&self) -> Option<P<Ty>> { - Some(P(self.clone())) + fn to_ty(&self) -> Option<Box<Ty>> { + Some(Box::new(self.clone())) } - fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self { + fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self { Self { span: path.span, kind: TyKind::Path(qself, path), @@ -90,10 +90,10 @@ impl RecoverQPath for Ty { impl RecoverQPath for Pat { const PATH_STYLE: PathStyle = PathStyle::Pat; - fn to_ty(&self) -> Option<P<Ty>> { + fn to_ty(&self) -> Option<Box<Ty>> { self.to_ty() } - fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self { + fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self { Self { span: path.span, kind: PatKind::Path(qself, path), @@ -104,10 +104,10 @@ impl RecoverQPath for Pat { } impl RecoverQPath for Expr { - fn to_ty(&self) -> Option<P<Ty>> { + fn to_ty(&self) -> Option<Box<Ty>> { self.to_ty() } - fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self { + fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self { Self { span: path.span, kind: ExprKind::Path(qself, path), @@ -463,8 +463,8 @@ impl<'a> Parser<'a> { pub(super) fn expected_one_of_not_found( &mut self, - edible: &[ExpTokenPair<'_>], - inedible: &[ExpTokenPair<'_>], + edible: &[ExpTokenPair], + inedible: &[ExpTokenPair], ) -> PResult<'a, ErrorGuaranteed> { debug!("expected_one_of_not_found(edible: {:?}, inedible: {:?})", edible, inedible); fn tokens_to_string(tokens: &[TokenType]) -> String { @@ -977,7 +977,7 @@ impl<'a> Parser<'a> { lo: Span, s: BlockCheckMode, maybe_struct_name: token::Token, - ) -> Option<PResult<'a, P<Block>>> { + ) -> Option<PResult<'a, Box<Block>>> { if self.token.is_ident() && self.look_ahead(1, |t| t == &token::Colon) { // We might be having a struct literal where people forgot to include the path: // fn foo() -> Foo { @@ -1042,7 +1042,7 @@ impl<'a> Parser<'a> { token: token::Token, lo: Span, decl_hi: Span, - ) -> PResult<'a, P<Expr>> { + ) -> PResult<'a, Box<Expr>> { err.span_label(lo.to(decl_hi), "while parsing the body of this closure"); let guar = match before.kind { token::OpenBrace if token.kind != token::OpenBrace => { @@ -1092,7 +1092,7 @@ impl<'a> Parser<'a> { /// Eats and discards tokens until one of `closes` is encountered. Respects token trees, /// passes through any errors encountered. Used for error recovery. - pub(super) fn eat_to_tokens(&mut self, closes: &[ExpTokenPair<'_>]) { + pub(super) fn eat_to_tokens(&mut self, closes: &[ExpTokenPair]) { if let Err(err) = self .parse_seq_to_before_tokens(closes, &[], SeqSep::none(), |p| Ok(p.parse_token_tree())) { @@ -1113,7 +1113,7 @@ impl<'a> Parser<'a> { pub(super) fn check_trailing_angle_brackets( &mut self, segment: &PathSegment, - end: &[ExpTokenPair<'_>], + end: &[ExpTokenPair], ) -> Option<ErrorGuaranteed> { if !self.may_recover() { return None; @@ -1196,7 +1196,7 @@ impl<'a> Parser<'a> { // second case. if self.look_ahead(position, |t| { trace!("check_trailing_angle_brackets: t={:?}", t); - end.iter().any(|exp| exp.tok == &t.kind) + end.iter().any(|exp| exp.tok == t.kind) }) { // Eat from where we started until the end token so that parsing can continue // as if we didn't have those extra angle brackets. @@ -1260,7 +1260,7 @@ impl<'a> Parser<'a> { pub(super) fn check_mistyped_turbofish_with_multiple_type_params( &mut self, mut e: Diag<'a>, - expr: &mut P<Expr>, + expr: &mut Box<Expr>, ) -> PResult<'a, ErrorGuaranteed> { if let ExprKind::Binary(binop, _, _) = &expr.kind && let ast::BinOpKind::Lt = binop.node @@ -1443,7 +1443,7 @@ impl<'a> Parser<'a> { &mut self, inner_op: &Expr, outer_op: &Spanned<AssocOp>, - ) -> PResult<'a, Option<P<Expr>>> { + ) -> PResult<'a, Option<Box<Expr>>> { debug_assert!( outer_op.node.is_comparison(), "check_no_chained_comparison: {:?} is not comparison", @@ -1595,7 +1595,7 @@ impl<'a> Parser<'a> { } /// Swift lets users write `Ty?` to mean `Option<Ty>`. Parse the construct and recover from it. - pub(super) fn maybe_recover_from_question_mark(&mut self, ty: P<Ty>) -> P<Ty> { + pub(super) fn maybe_recover_from_question_mark(&mut self, ty: Box<Ty>) -> Box<Ty> { if self.token == token::Question { self.bump(); let guar = self.dcx().emit_err(QuestionMarkInType { @@ -1690,10 +1690,10 @@ impl<'a> Parser<'a> { pub(super) fn recover_from_prefix_increment( &mut self, - operand_expr: P<Expr>, + operand_expr: Box<Expr>, op_span: Span, start_stmt: bool, - ) -> PResult<'a, P<Expr>> { + ) -> PResult<'a, Box<Expr>> { let standalone = if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr }; let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre }; self.recover_from_inc_dec(operand_expr, kind, op_span) @@ -1701,10 +1701,10 @@ impl<'a> Parser<'a> { pub(super) fn recover_from_postfix_increment( &mut self, - operand_expr: P<Expr>, + operand_expr: Box<Expr>, op_span: Span, start_stmt: bool, - ) -> PResult<'a, P<Expr>> { + ) -> PResult<'a, Box<Expr>> { let kind = IncDecRecovery { standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr }, op: IncOrDec::Inc, @@ -1715,10 +1715,10 @@ impl<'a> Parser<'a> { pub(super) fn recover_from_postfix_decrement( &mut self, - operand_expr: P<Expr>, + operand_expr: Box<Expr>, op_span: Span, start_stmt: bool, - ) -> PResult<'a, P<Expr>> { + ) -> PResult<'a, Box<Expr>> { let kind = IncDecRecovery { standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr }, op: IncOrDec::Dec, @@ -1729,10 +1729,10 @@ impl<'a> Parser<'a> { fn recover_from_inc_dec( &mut self, - base: P<Expr>, + base: Box<Expr>, kind: IncDecRecovery, op_span: Span, - ) -> PResult<'a, P<Expr>> { + ) -> PResult<'a, Box<Expr>> { let mut err = self.dcx().struct_span_err( op_span, format!("Rust has no {} {} operator", kind.fixity, kind.op.name()), @@ -1833,8 +1833,8 @@ impl<'a> Parser<'a> { /// tail, and combines them into a `<Ty>::AssocItem` expression/pattern/type. pub(super) fn maybe_recover_from_bad_qpath<T: RecoverQPath>( &mut self, - base: P<T>, - ) -> PResult<'a, P<T>> { + base: Box<T>, + ) -> PResult<'a, Box<T>> { if !self.may_recover() { return Ok(base); } @@ -1853,8 +1853,8 @@ impl<'a> Parser<'a> { pub(super) fn maybe_recover_from_bad_qpath_stage_2<T: RecoverQPath>( &mut self, ty_span: Span, - ty: P<Ty>, - ) -> PResult<'a, P<T>> { + ty: Box<Ty>, + ) -> PResult<'a, Box<T>> { self.expect(exp!(PathSep))?; let mut path = ast::Path { segments: ThinVec::new(), span: DUMMY_SP, tokens: None }; @@ -1867,7 +1867,7 @@ impl<'a> Parser<'a> { }); let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`. - Ok(P(T::recovered(Some(P(QSelf { ty, path_span, position: 0 })), path))) + Ok(Box::new(T::recovered(Some(Box::new(QSelf { ty, path_span, position: 0 })), path))) } /// This function gets called in places where a semicolon is NOT expected and if there's a @@ -1970,7 +1970,7 @@ impl<'a> Parser<'a> { pub(super) fn recover_incorrect_await_syntax( &mut self, await_sp: Span, - ) -> PResult<'a, P<Expr>> { + ) -> PResult<'a, Box<Expr>> { let (hi, expr, is_question) = if self.token == token::Bang { // Handle `await!(<expr>)`. self.recover_await_macro()? @@ -1982,7 +1982,7 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr) } - fn recover_await_macro(&mut self) -> PResult<'a, (Span, P<Expr>, bool)> { + fn recover_await_macro(&mut self) -> PResult<'a, (Span, Box<Expr>, bool)> { self.expect(exp!(Bang))?; self.expect(exp!(OpenParen))?; let expr = self.parse_expr()?; @@ -1990,7 +1990,7 @@ impl<'a> Parser<'a> { Ok((self.prev_token.span, expr, false)) } - fn recover_await_prefix(&mut self, await_sp: Span) -> PResult<'a, (Span, P<Expr>, bool)> { + fn recover_await_prefix(&mut self, await_sp: Span) -> PResult<'a, (Span, Box<Expr>, bool)> { let is_question = self.eat(exp!(Question)); // Handle `await? <expr>`. let expr = if self.token == token::OpenBrace { // Handle `await { <expr> }`. @@ -2052,7 +2052,7 @@ impl<'a> Parser<'a> { } } - pub(super) fn try_macro_suggestion(&mut self) -> PResult<'a, P<Expr>> { + pub(super) fn try_macro_suggestion(&mut self) -> PResult<'a, Box<Expr>> { let is_try = self.token.is_keyword(kw::Try); let is_questionmark = self.look_ahead(1, |t| t == &token::Bang); //check for ! let is_open = self.look_ahead(2, |t| t == &token::OpenParen); //check for ( @@ -2120,11 +2120,11 @@ impl<'a> Parser<'a> { pub(super) fn recover_seq_parse_error( &mut self, - open: ExpTokenPair<'_>, - close: ExpTokenPair<'_>, + open: ExpTokenPair, + close: ExpTokenPair, lo: Span, err: Diag<'a>, - ) -> P<Expr> { + ) -> Box<Expr> { let guar = err.emit(); // Recover from parse error, callers expect the closing delim to be consumed. self.consume_block(open, close, ConsumeClosingDelim::Yes); @@ -2244,9 +2244,10 @@ impl<'a> Parser<'a> { pub(super) fn parameter_without_type( &mut self, err: &mut Diag<'_>, - pat: P<ast::Pat>, + pat: Box<ast::Pat>, require_name: bool, first_param: bool, + fn_parse_mode: &crate::parser::item::FnParseMode, ) -> Option<Ident> { // If we find a pattern followed by an identifier, it could be an (incorrect) // C-style parameter declaration. @@ -2269,7 +2270,14 @@ impl<'a> Parser<'a> { || self.token == token::Lt || self.token == token::CloseParen) { - let rfc_note = "anonymous parameters are removed in the 2018 edition (see RFC 1685)"; + let maybe_emit_anon_params_note = |this: &mut Self, err: &mut Diag<'_>| { + let ed = this.token.span.with_neighbor(this.prev_token.span).edition(); + if matches!(fn_parse_mode.context, crate::parser::item::FnContext::Trait) + && (fn_parse_mode.req_name)(ed) + { + err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)"); + } + }; let (ident, self_sugg, param_sugg, type_sugg, self_span, param_span, type_span) = match pat.kind { @@ -2306,7 +2314,7 @@ impl<'a> Parser<'a> { "_: ".to_string(), Applicability::MachineApplicable, ); - err.note(rfc_note); + maybe_emit_anon_params_note(self, err); } return None; @@ -2314,7 +2322,13 @@ impl<'a> Parser<'a> { }; // `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}` - if first_param { + if first_param + // Only when the fn is a method, we emit this suggestion. + && matches!( + fn_parse_mode.context, + FnContext::Trait | FnContext::Impl + ) + { err.span_suggestion_verbose( self_span, "if this is a `self` type, give it a parameter name", @@ -2338,7 +2352,7 @@ impl<'a> Parser<'a> { type_sugg, Applicability::MachineApplicable, ); - err.note(rfc_note); + maybe_emit_anon_params_note(self, err); // Don't attempt to recover by using the `X` in `X<Y>` as the parameter name. return if self.token == token::Lt { None } else { Some(ident) }; @@ -2346,7 +2360,7 @@ impl<'a> Parser<'a> { None } - pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> { + pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (Box<ast::Pat>, Box<ast::Ty>)> { let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?; self.expect(exp!(Colon))?; let ty = self.parse_ty()?; @@ -2354,8 +2368,12 @@ impl<'a> Parser<'a> { self.dcx().emit_err(PatternMethodParamWithoutBody { span: pat.span }); // Pretend the pattern is `_`, to avoid duplicate errors from AST validation. - let pat = - P(Pat { kind: PatKind::Wild, span: pat.span, id: ast::DUMMY_NODE_ID, tokens: None }); + let pat = Box::new(Pat { + kind: PatKind::Wild, + span: pat.span, + id: ast::DUMMY_NODE_ID, + tokens: None, + }); Ok((pat, ty)) } @@ -2368,8 +2386,8 @@ impl<'a> Parser<'a> { pub(super) fn consume_block( &mut self, - open: ExpTokenPair<'_>, - close: ExpTokenPair<'_>, + open: ExpTokenPair, + close: ExpTokenPair, consume_close: ConsumeClosingDelim, ) { let mut brace_depth = 0; @@ -2506,7 +2524,7 @@ impl<'a> Parser<'a> { /// - Single-segment paths (i.e. standalone generic const parameters). /// All other expressions that can be parsed will emit an error suggesting the expression be /// wrapped in braces. - pub(super) fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P<Expr>> { + pub(super) fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, Box<Expr>> { let start = self.token.span; let attrs = self.parse_outer_attributes()?; let (expr, _) = @@ -2688,7 +2706,7 @@ impl<'a> Parser<'a> { pub(crate) fn recover_unbraced_const_arg_that_can_begin_ty( &mut self, mut snapshot: SnapshotParser<'a>, - ) -> Option<P<ast::Expr>> { + ) -> Option<Box<ast::Expr>> { match (|| { let attrs = self.parse_outer_attributes()?; snapshot.parse_expr_res(Restrictions::CONST_EXPR, attrs) @@ -2724,9 +2742,9 @@ impl<'a> Parser<'a> { /// `for` loop, `let`, &c. (in contrast to subpatterns within such). pub(crate) fn maybe_recover_colon_colon_in_pat_typo( &mut self, - mut first_pat: P<Pat>, + mut first_pat: Box<Pat>, expected: Option<Expected>, - ) -> P<Pat> { + ) -> Box<Pat> { if token::Colon != self.token.kind { return first_pat; } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 35b987cf50f..f0f58e901a9 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -6,7 +6,6 @@ use core::ops::{Bound, ControlFlow}; use ast::mut_visit::{self, MutVisitor}; use ast::token::IdentIsRaw; use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered}; -use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, Token, TokenKind}; use rustc_ast::tokenstream::TokenTree; use rustc_ast::util::case::Case; @@ -56,7 +55,7 @@ pub(super) enum DestructuredFloat { impl<'a> Parser<'a> { /// Parses an expression. #[inline] - pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> { + pub fn parse_expr(&mut self) -> PResult<'a, Box<Expr>> { self.current_closure.take(); let attrs = self.parse_outer_attributes()?; @@ -64,7 +63,7 @@ impl<'a> Parser<'a> { } /// Parses an expression, forcing tokens to be collected. - pub fn parse_expr_force_collect(&mut self) -> PResult<'a, P<Expr>> { + pub fn parse_expr_force_collect(&mut self) -> PResult<'a, Box<Expr>> { self.current_closure.take(); // If the expression is associative (e.g. `1 + 2`), then any preceding @@ -90,7 +89,10 @@ impl<'a> Parser<'a> { self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value }) } - fn parse_expr_catch_underscore(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> { + fn parse_expr_catch_underscore( + &mut self, + restrictions: Restrictions, + ) -> PResult<'a, Box<Expr>> { let attrs = self.parse_outer_attributes()?; match self.parse_expr_res(restrictions, attrs) { Ok((expr, _)) => Ok(expr), @@ -109,7 +111,7 @@ impl<'a> Parser<'a> { } /// Parses a sequence of expressions delimited by parentheses. - fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<P<Expr>>> { + fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<Box<Expr>>> { self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore(Restrictions::empty())) .map(|(r, _)| r) } @@ -120,7 +122,7 @@ impl<'a> Parser<'a> { &mut self, r: Restrictions, attrs: AttrWrapper, - ) -> PResult<'a, (P<Expr>, bool)> { + ) -> PResult<'a, (Box<Expr>, bool)> { self.with_res(r, |this| this.parse_expr_assoc_with(Bound::Unbounded, attrs)) } @@ -131,7 +133,7 @@ impl<'a> Parser<'a> { &mut self, min_prec: Bound<ExprPrecedence>, attrs: AttrWrapper, - ) -> PResult<'a, (P<Expr>, bool)> { + ) -> PResult<'a, (Box<Expr>, bool)> { let lhs = if self.token.is_range_separator() { return self.parse_expr_prefix_range(attrs).map(|res| (res, false)); } else { @@ -147,8 +149,8 @@ impl<'a> Parser<'a> { &mut self, min_prec: Bound<ExprPrecedence>, starts_stmt: bool, - mut lhs: P<Expr>, - ) -> PResult<'a, (P<Expr>, bool)> { + mut lhs: Box<Expr>, + ) -> PResult<'a, (Box<Expr>, bool)> { let mut parsed_something = false; if !self.should_continue_as_assoc_expr(&lhs) { return Ok((lhs, parsed_something)); @@ -414,10 +416,10 @@ impl<'a> Parser<'a> { fn parse_expr_range( &mut self, prec: ExprPrecedence, - lhs: P<Expr>, + lhs: Box<Expr>, limits: RangeLimits, cur_op_span: Span, - ) -> PResult<'a, P<Expr>> { + ) -> PResult<'a, Box<Expr>> { let rhs = if self.is_at_start_of_range_notation_rhs() { let maybe_lt = self.token; let attrs = self.parse_outer_attributes()?; @@ -448,7 +450,7 @@ impl<'a> Parser<'a> { } /// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`. - fn parse_expr_prefix_range(&mut self, attrs: AttrWrapper) -> PResult<'a, P<Expr>> { + fn parse_expr_prefix_range(&mut self, attrs: AttrWrapper) -> PResult<'a, Box<Expr>> { if !attrs.is_empty() { let err = errors::DotDotRangeAttribute { span: self.token.span }; self.dcx().emit_err(err); @@ -490,7 +492,7 @@ impl<'a> Parser<'a> { } /// Parses a prefix-unary-operator expr. - fn parse_expr_prefix(&mut self, attrs: AttrWrapper) -> PResult<'a, P<Expr>> { + fn parse_expr_prefix(&mut self, attrs: AttrWrapper) -> PResult<'a, Box<Expr>> { let lo = self.token.span; macro_rules! make_it { @@ -564,7 +566,7 @@ impl<'a> Parser<'a> { } } - fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> { + fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, Box<Expr>)> { self.bump(); let attrs = self.parse_outer_attributes()?; let expr = if self.token.is_range_separator() { @@ -653,12 +655,12 @@ impl<'a> Parser<'a> { fn parse_assoc_op_cast( &mut self, - lhs: P<Expr>, + lhs: Box<Expr>, lhs_span: Span, op_span: Span, - expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind, - ) -> PResult<'a, P<Expr>> { - let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| { + expr_kind: fn(Box<Expr>, Box<Ty>) -> ExprKind, + ) -> PResult<'a, Box<Expr>> { + let mk_expr = |this: &mut Self, lhs: Box<Expr>, rhs: Box<Ty>| { this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, op_span, rhs.span), expr_kind(lhs, rhs)) }; @@ -873,7 +875,7 @@ impl<'a> Parser<'a> { } /// Parses `a.b` or `a(13)` or `a[4]` or just `a`. - fn parse_expr_dot_or_call(&mut self, attrs: AttrWrapper) -> PResult<'a, P<Expr>> { + fn parse_expr_dot_or_call(&mut self, attrs: AttrWrapper) -> PResult<'a, Box<Expr>> { self.collect_tokens_for_expr(attrs, |this, attrs| { let base = this.parse_expr_bottom()?; let span = this.interpolated_or_expr_span(&base); @@ -884,9 +886,9 @@ impl<'a> Parser<'a> { pub(super) fn parse_expr_dot_or_call_with( &mut self, mut attrs: ast::AttrVec, - mut e: P<Expr>, + mut e: Box<Expr>, lo: Span, - ) -> PResult<'a, P<Expr>> { + ) -> PResult<'a, Box<Expr>> { let mut res = ensure_sufficient_stack(|| { loop { let has_question = @@ -945,8 +947,8 @@ impl<'a> Parser<'a> { pub(super) fn parse_dot_suffix_expr( &mut self, lo: Span, - base: P<Expr>, - ) -> PResult<'a, P<Expr>> { + base: Box<Expr>, + ) -> PResult<'a, Box<Expr>> { // At this point we've consumed something like `expr.` and `self.token` holds the token // after the dot. match self.token.uninterpolate().kind { @@ -1232,10 +1234,10 @@ impl<'a> Parser<'a> { &self, lo: Span, ident_span: Span, - base: P<Expr>, + base: Box<Expr>, field: Symbol, suffix: Option<Symbol>, - ) -> P<Expr> { + ) -> Box<Expr> { if let Some(suffix) = suffix { self.expect_no_tuple_index_suffix(ident_span, suffix); } @@ -1243,7 +1245,7 @@ impl<'a> Parser<'a> { } /// Parse a function call expression, `expr(...)`. - fn parse_expr_fn_call(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> { + fn parse_expr_fn_call(&mut self, lo: Span, fun: Box<Expr>) -> Box<Expr> { let snapshot = if self.token == token::OpenParen { Some((self.create_snapshot_for_diagnostic(), fun.kind.clone())) } else { @@ -1267,9 +1269,9 @@ impl<'a> Parser<'a> { &mut self, lo: Span, open_paren: Span, - seq: PResult<'a, P<Expr>>, + seq: PResult<'a, Box<Expr>>, snapshot: Option<(SnapshotParser<'a>, ExprKind)>, - ) -> PResult<'a, P<Expr>> { + ) -> PResult<'a, Box<Expr>> { match (self.may_recover(), seq, snapshot) { (true, Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => { snapshot.bump(); // `(` @@ -1325,7 +1327,7 @@ impl<'a> Parser<'a> { } /// Parse an indexing expression `expr[...]`. - fn parse_expr_index(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> { + fn parse_expr_index(&mut self, lo: Span, base: Box<Expr>) -> PResult<'a, Box<Expr>> { let prev_span = self.prev_token.span; let open_delim_span = self.token.span; self.bump(); // `[` @@ -1339,7 +1341,7 @@ impl<'a> Parser<'a> { } /// Assuming we have just parsed `.`, continue parsing into an expression. - fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> { + fn parse_dot_suffix(&mut self, self_arg: Box<Expr>, lo: Span) -> PResult<'a, Box<Expr>> { if self.token_uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await)) { return Ok(self.mk_await_expr(self_arg, lo)); } @@ -1404,7 +1406,7 @@ impl<'a> Parser<'a> { /// /// N.B., this does not parse outer attributes, and is private because it only works /// correctly if called from `parse_expr_dot_or_call`. - fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> { + fn parse_expr_bottom(&mut self) -> PResult<'a, Box<Expr>> { maybe_recover_from_interpolated_ty_qpath!(self, true); let span = self.token.span; @@ -1556,7 +1558,7 @@ impl<'a> Parser<'a> { }) } - fn parse_expr_lit(&mut self) -> PResult<'a, P<Expr>> { + fn parse_expr_lit(&mut self) -> PResult<'a, Box<Expr>> { let lo = self.token.span; match self.parse_opt_token_lit() { Some((token_lit, _)) => { @@ -1567,7 +1569,7 @@ impl<'a> Parser<'a> { } } - fn parse_expr_tuple_parens(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> { + fn parse_expr_tuple_parens(&mut self, restrictions: Restrictions) -> PResult<'a, Box<Expr>> { let lo = self.token.span; self.expect(exp!(OpenParen))?; let (es, trailing_comma) = match self.parse_seq_to_end( @@ -1596,7 +1598,7 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr) } - fn parse_expr_array_or_repeat(&mut self, close: ExpTokenPair<'_>) -> PResult<'a, P<Expr>> { + fn parse_expr_array_or_repeat(&mut self, close: ExpTokenPair) -> PResult<'a, Box<Expr>> { let lo = self.token.span; self.bump(); // `[` or other open delim @@ -1627,7 +1629,7 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr) } - fn parse_expr_path_start(&mut self) -> PResult<'a, P<Expr>> { + fn parse_expr_path_start(&mut self) -> PResult<'a, Box<Expr>> { let maybe_eq_tok = self.prev_token; let (qself, path) = if self.eat_lt() { let lt_span = self.prev_token.span; @@ -1653,7 +1655,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(errors::MacroInvocationWithQualifiedPath(path.span)); } let lo = path.span; - let mac = P(MacCall { path, args: self.parse_delim_args()? }); + let mac = Box::new(MacCall { path, args: self.parse_delim_args()? }); (lo.to(self.prev_token.span), ExprKind::MacCall(mac)) } else if self.check(exp!(OpenBrace)) && let Some(expr) = self.maybe_parse_struct_expr(&qself, &path) @@ -1675,7 +1677,7 @@ impl<'a> Parser<'a> { &mut self, label_: Label, mut consume_colon: bool, - ) -> PResult<'a, P<Expr>> { + ) -> PResult<'a, Box<Expr>> { let lo = label_.ident.span; let label = Some(label_); let ate_colon = self.eat(exp!(Colon)); @@ -1810,7 +1812,7 @@ impl<'a> Parser<'a> { } /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead. - fn recover_do_catch(&mut self) -> PResult<'a, P<Expr>> { + fn recover_do_catch(&mut self) -> PResult<'a, Box<Expr>> { let lo = self.token.span; self.bump(); // `do` @@ -1823,12 +1825,12 @@ impl<'a> Parser<'a> { } /// Parse an expression if the token can begin one. - fn parse_expr_opt(&mut self) -> PResult<'a, Option<P<Expr>>> { + fn parse_expr_opt(&mut self) -> PResult<'a, Option<Box<Expr>>> { Ok(if self.token.can_begin_expr() { Some(self.parse_expr()?) } else { None }) } /// Parse `"return" expr?`. - fn parse_expr_return(&mut self) -> PResult<'a, P<Expr>> { + fn parse_expr_return(&mut self) -> PResult<'a, Box<Expr>> { let lo = self.prev_token.span; let kind = ExprKind::Ret(self.parse_expr_opt()?); let expr = self.mk_expr(lo.to(self.prev_token.span), kind); @@ -1836,7 +1838,7 @@ impl<'a> Parser<'a> { } /// Parse `"do" "yeet" expr?`. - fn parse_expr_yeet(&mut self) -> PResult<'a, P<Expr>> { + fn parse_expr_yeet(&mut self) -> PResult<'a, Box<Expr>> { let lo = self.token.span; self.bump(); // `do` @@ -1851,7 +1853,7 @@ impl<'a> Parser<'a> { } /// Parse `"become" expr`, with `"become"` token already eaten. - fn parse_expr_become(&mut self) -> PResult<'a, P<Expr>> { + fn parse_expr_become(&mut self) -> PResult<'a, Box<Expr>> { let lo = self.prev_token.span; let kind = ExprKind::Become(self.parse_expr()?); let span = lo.to(self.prev_token.span); @@ -1868,7 +1870,7 @@ impl<'a> Parser<'a> { /// `break 'lbl: loop {}`); a labeled break with an unlabeled loop as its value /// expression only gets a warning for compatibility reasons; and a labeled break /// with a labeled loop does not even get a warning because there is no ambiguity. - fn parse_expr_break(&mut self) -> PResult<'a, P<Expr>> { + fn parse_expr_break(&mut self) -> PResult<'a, Box<Expr>> { let lo = self.prev_token.span; let mut label = self.eat_label(); let kind = if self.token == token::Colon @@ -1930,7 +1932,7 @@ impl<'a> Parser<'a> { } /// Parse `"continue" label?`. - fn parse_expr_continue(&mut self, lo: Span) -> PResult<'a, P<Expr>> { + fn parse_expr_continue(&mut self, lo: Span) -> PResult<'a, Box<Expr>> { let mut label = self.eat_label(); // Recover `continue label` -> `continue 'label` @@ -1947,7 +1949,7 @@ impl<'a> Parser<'a> { } /// Parse `"yield" expr?`. - fn parse_expr_yield(&mut self) -> PResult<'a, P<Expr>> { + fn parse_expr_yield(&mut self) -> PResult<'a, Box<Expr>> { let lo = self.prev_token.span; let kind = ExprKind::Yield(YieldKind::Prefix(self.parse_expr_opt()?)); let span = lo.to(self.prev_token.span); @@ -1957,7 +1959,7 @@ impl<'a> Parser<'a> { } /// Parse `builtin # ident(args,*)`. - fn parse_expr_builtin(&mut self) -> PResult<'a, P<Expr>> { + fn parse_expr_builtin(&mut self) -> PResult<'a, Box<Expr>> { self.parse_builtin(|this, lo, ident| { Ok(match ident.name { sym::offset_of => Some(this.parse_expr_offset_of(lo)?), @@ -2005,7 +2007,7 @@ impl<'a> Parser<'a> { } /// Built-in macro for `offset_of!` expressions. - pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, P<Expr>> { + pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, Box<Expr>> { let container = self.parse_ty()?; self.expect(exp!(Comma))?; @@ -2033,7 +2035,7 @@ impl<'a> Parser<'a> { } /// Built-in macro for type ascription expressions. - pub(crate) fn parse_expr_type_ascribe(&mut self, lo: Span) -> PResult<'a, P<Expr>> { + pub(crate) fn parse_expr_type_ascribe(&mut self, lo: Span) -> PResult<'a, Box<Expr>> { let expr = self.parse_expr()?; self.expect(exp!(Comma))?; let ty = self.parse_ty()?; @@ -2045,7 +2047,7 @@ impl<'a> Parser<'a> { &mut self, lo: Span, kind: UnsafeBinderCastKind, - ) -> PResult<'a, P<Expr>> { + ) -> PResult<'a, Box<Expr>> { let expr = self.parse_expr()?; let ty = if self.eat(exp!(Comma)) { Some(self.parse_ty()?) } else { None }; let span = lo.to(self.token.span); @@ -2075,7 +2077,7 @@ impl<'a> Parser<'a> { (token::Lit { symbol: name, suffix: None, kind: token::Char }, span) } - fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit { + pub fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit { ast::MetaItemLit { symbol: name, suffix: None, @@ -2084,7 +2086,7 @@ impl<'a> Parser<'a> { } } - fn handle_missing_lit<L>( + pub fn handle_missing_lit<L>( &mut self, mk_lit_char: impl FnOnce(Symbol, Span) -> L, ) -> PResult<'a, L> { @@ -2154,8 +2156,8 @@ impl<'a> Parser<'a> { /// Keep this in sync with `Token::can_begin_literal_maybe_minus` and /// `Lit::from_token` (excluding unary negation). - fn eat_token_lit(&mut self) -> Option<token::Lit> { - let check_expr = |expr: P<Expr>| { + pub fn eat_token_lit(&mut self) -> Option<token::Lit> { + let check_expr = |expr: Box<Expr>| { if let ast::ExprKind::Lit(token_lit) = expr.kind { Some(token_lit) } else if let ast::ExprKind::Unary(UnOp::Neg, inner) = &expr.kind @@ -2243,7 +2245,7 @@ impl<'a> Parser<'a> { /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). /// Keep this in sync with `Token::can_begin_literal_maybe_minus`. - pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> { + pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, Box<Expr>> { if let Some(expr) = self.eat_metavar_seq_with_matcher( |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }), |this| { @@ -2290,7 +2292,7 @@ impl<'a> Parser<'a> { /// Emits a suggestion if it looks like the user meant an array but /// accidentally used braces, causing the code to be interpreted as a block /// expression. - fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<P<Expr>> { + fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<Box<Expr>> { let mut snapshot = self.create_snapshot_for_diagnostic(); match snapshot.parse_expr_array_or_repeat(exp!(CloseBrace)) { Ok(arr) => { @@ -2360,7 +2362,7 @@ impl<'a> Parser<'a> { opt_label: Option<Label>, lo: Span, blk_mode: BlockCheckMode, - ) -> PResult<'a, P<Expr>> { + ) -> PResult<'a, Box<Expr>> { if self.may_recover() && self.is_array_like_block() { if let Some(arr) = self.maybe_suggest_brackets_instead_of_braces(lo) { return Ok(arr); @@ -2383,32 +2385,36 @@ impl<'a> Parser<'a> { } /// Parse a block which takes no attributes and has no label - fn parse_simple_block(&mut self) -> PResult<'a, P<Expr>> { + fn parse_simple_block(&mut self) -> PResult<'a, Box<Expr>> { let blk = self.parse_block()?; Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None))) } /// Parses a closure expression (e.g., `move |args| expr`). - fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> { + fn parse_expr_closure(&mut self) -> PResult<'a, Box<Expr>> { let lo = self.token.span; let before = self.prev_token; let binder = if self.check_keyword(exp!(For)) { let lo = self.token.span; - let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?; + let (bound_vars, _) = self.parse_higher_ranked_binder()?; let span = lo.to(self.prev_token.span); self.psess.gated_spans.gate(sym::closure_lifetime_binder, span); - ClosureBinder::For { span, generic_params: lifetime_defs } + ClosureBinder::For { span, generic_params: bound_vars } } else { ClosureBinder::NotPresent }; let constness = self.parse_closure_constness(); - let movability = - if self.eat_keyword(exp!(Static)) { Movability::Static } else { Movability::Movable }; + let movability = if self.eat_keyword(exp!(Static)) { + self.psess.gated_spans.gate(sym::coroutines, self.prev_token.span); + Movability::Static + } else { + Movability::Movable + }; let coroutine_kind = if self.token_uninterpolated_span().at_least_rust_2018() { self.parse_coroutine_kind(Case::Sensitive) @@ -2494,7 +2500,7 @@ impl<'a> Parser<'a> { } /// If an explicit return type is given, require a block to appear (RFC 968). - fn parse_closure_block_body(&mut self, ret_span: Span) -> PResult<'a, P<Expr>> { + fn parse_closure_block_body(&mut self, ret_span: Span) -> PResult<'a, Box<Expr>> { if self.may_recover() && self.token.can_begin_expr() && self.token.kind != TokenKind::OpenBrace @@ -2565,7 +2571,7 @@ impl<'a> Parser<'a> { } /// Parses the `|arg, arg|` header of a closure. - fn parse_fn_block_decl(&mut self) -> PResult<'a, (P<FnDecl>, Span)> { + fn parse_fn_block_decl(&mut self) -> PResult<'a, (Box<FnDecl>, Span)> { let arg_start = self.token.span.lo(); let inputs = if self.eat(exp!(OrOr)) { @@ -2587,7 +2593,7 @@ impl<'a> Parser<'a> { let output = self.parse_ret_ty(AllowPlus::Yes, RecoverQPath::Yes, RecoverReturnSign::Yes)?; - Ok((P(FnDecl { inputs, output }), arg_span)) + Ok((Box::new(FnDecl { inputs, output }), arg_span)) } /// Parses a parameter in a closure header (e.g., `|arg, arg|`). @@ -2618,7 +2624,7 @@ impl<'a> Parser<'a> { } /// Parses an `if` expression (`if` token already eaten). - fn parse_expr_if(&mut self) -> PResult<'a, P<Expr>> { + fn parse_expr_if(&mut self) -> PResult<'a, Box<Expr>> { let lo = self.prev_token.span; // Scoping code checks the top level edition of the `if`; let's match it here. // The `CondChecker` also checks the edition of the `let` itself, just to make sure. @@ -2627,7 +2633,7 @@ impl<'a> Parser<'a> { self.parse_if_after_cond(lo, cond) } - fn parse_if_after_cond(&mut self, lo: Span, mut cond: P<Expr>) -> PResult<'a, P<Expr>> { + fn parse_if_after_cond(&mut self, lo: Span, mut cond: Box<Expr>) -> PResult<'a, Box<Expr>> { let cond_span = cond.span; // Tries to interpret `cond` as either a missing expression if it's a block, // or as an unfinished expression if it's a binop and the RHS is a block. @@ -2737,7 +2743,10 @@ impl<'a> Parser<'a> { /// i.e. the same span we use to later decide whether the drop behaviour should be that of /// edition `..=2021` or that of `2024..`. // Public because it is used in rustfmt forks such as https://github.com/tucant/rustfmt/blob/30c83df9e1db10007bdd16dafce8a86b404329b2/src/parse/macros/html.rs#L57 for custom if expressions. - pub fn parse_expr_cond(&mut self, let_chains_policy: LetChainsPolicy) -> PResult<'a, P<Expr>> { + pub fn parse_expr_cond( + &mut self, + let_chains_policy: LetChainsPolicy, + ) -> PResult<'a, Box<Expr>> { let attrs = self.parse_outer_attributes()?; let (mut cond, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, attrs)?; @@ -2748,7 +2757,7 @@ impl<'a> Parser<'a> { } /// Parses a `let $pat = $expr` pseudo-expression. - fn parse_expr_let(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> { + fn parse_expr_let(&mut self, restrictions: Restrictions) -> PResult<'a, Box<Expr>> { let recovered = if !restrictions.contains(Restrictions::ALLOW_LET) { let err = errors::ExpectedExpressionFoundLet { span: self.token.span, @@ -2790,7 +2799,7 @@ impl<'a> Parser<'a> { } /// Parses an `else { ... }` expression (`else` token already eaten). - fn parse_expr_else(&mut self) -> PResult<'a, P<Expr>> { + fn parse_expr_else(&mut self) -> PResult<'a, Box<Expr>> { let else_span = self.prev_token.span; // `else` let attrs = self.parse_outer_attributes()?; // For recovery. let expr = if self.eat_keyword(exp!(If)) { @@ -2888,7 +2897,7 @@ impl<'a> Parser<'a> { } } - fn error_on_extra_if(&mut self, cond: &P<Expr>) -> PResult<'a, ()> { + fn error_on_extra_if(&mut self, cond: &Box<Expr>) -> PResult<'a, ()> { if let ExprKind::Binary(Spanned { span: binop_span, node: binop }, _, right) = &cond.kind && let BinOpKind::And = binop && let ExprKind::If(cond, ..) = &right.kind @@ -2901,7 +2910,7 @@ impl<'a> Parser<'a> { } } - fn parse_for_head(&mut self) -> PResult<'a, (P<Pat>, P<Expr>)> { + fn parse_for_head(&mut self) -> PResult<'a, (Box<Pat>, Box<Expr>)> { let begin_paren = if self.token == token::OpenParen { // Record whether we are about to parse `for (`. // This is used below for recovery in case of `for ( $stuff ) $block` @@ -2967,7 +2976,7 @@ impl<'a> Parser<'a> { } /// Parses `for await? <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten). - fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> { + fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, Box<Expr>> { let is_await = self.token_uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await)); @@ -3028,6 +3037,8 @@ impl<'a> Parser<'a> { let span = self.token.span; self.bump(); (span, errors::MissingInInForLoopSub::InNotOf) + } else if self.eat(exp!(Eq)) { + (self.prev_token.span, errors::MissingInInForLoopSub::InNotEq) } else { (self.prev_token.span.between(self.token.span), errors::MissingInInForLoopSub::AddIn) }; @@ -3036,7 +3047,7 @@ impl<'a> Parser<'a> { } /// Parses a `while` or `while let` expression (`while` token already eaten). - fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> { + fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, Box<Expr>> { let policy = LetChainsPolicy::EditionDependent { current_edition: lo.edition() }; let cond = self.parse_expr_cond(policy).map_err(|mut err| { err.span_label(lo, "while parsing the condition of this `while` expression"); @@ -3064,7 +3075,7 @@ impl<'a> Parser<'a> { } /// Parses `loop { ... }` (`loop` token already eaten). - fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> { + fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, Box<Expr>> { let loop_span = self.prev_token.span; let (attrs, body) = self.parse_inner_attrs_and_block( // Only suggest moving erroneous block label to the loop header @@ -3083,7 +3094,7 @@ impl<'a> Parser<'a> { if let Some((ident, is_raw)) = self.token.lifetime() { // Disallow `'fn`, but with a better error message than `expect_lifetime`. if matches!(is_raw, IdentIsRaw::No) && ident.without_first_quote().is_reserved() { - self.dcx().emit_err(errors::InvalidLabel { span: ident.span, name: ident.name }); + self.dcx().emit_err(errors::KeywordLabel { span: ident.span }); } self.bump(); @@ -3094,7 +3105,7 @@ impl<'a> Parser<'a> { } /// Parses a `match ... { ... }` expression (`match` token already eaten). - fn parse_expr_match(&mut self) -> PResult<'a, P<Expr>> { + fn parse_expr_match(&mut self) -> PResult<'a, Box<Expr>> { let match_span = self.prev_token.span; let attrs = self.parse_outer_attributes()?; let (scrutinee, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs)?; @@ -3108,9 +3119,9 @@ impl<'a> Parser<'a> { &mut self, lo: Span, match_span: Span, - scrutinee: P<Expr>, + scrutinee: Box<Expr>, match_kind: MatchKind, - ) -> PResult<'a, P<Expr>> { + ) -> PResult<'a, Box<Expr>> { if let Err(mut e) = self.expect(exp!(OpenBrace)) { if self.token == token::Semi { e.span_suggestion_short( @@ -3167,7 +3178,7 @@ impl<'a> Parser<'a> { /// Attempt to recover from match arm body with statements and no surrounding braces. fn parse_arm_body_missing_braces( &mut self, - first_expr: &P<Expr>, + first_expr: &Box<Expr>, arrow_span: Span, ) -> Option<(Span, ErrorGuaranteed)> { if self.token != token::Semi { @@ -3439,7 +3450,7 @@ impl<'a> Parser<'a> { }) } - fn parse_match_arm_guard(&mut self) -> PResult<'a, Option<P<Expr>>> { + fn parse_match_arm_guard(&mut self) -> PResult<'a, Option<Box<Expr>>> { // Used to check the `if_let_guard` feature mostly by scanning // `&&` tokens. fn has_let_expr(expr: &Expr) -> bool { @@ -3470,7 +3481,7 @@ impl<'a> Parser<'a> { Ok(Some(cond)) } - fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (P<Pat>, Option<P<Expr>>)> { + fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Box<Pat>, Option<Box<Expr>>)> { if self.token == token::OpenParen { let left = self.token.span; let pat = self.parse_pat_no_top_guard( @@ -3510,7 +3521,7 @@ impl<'a> Parser<'a> { } } - fn parse_match_guard_condition(&mut self) -> PResult<'a, P<Expr>> { + fn parse_match_guard_condition(&mut self) -> PResult<'a, Box<Expr>> { let attrs = self.parse_outer_attributes()?; match self.parse_expr_res(Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD, attrs) { Ok((expr, _)) => Ok(expr), @@ -3544,7 +3555,7 @@ impl<'a> Parser<'a> { } /// Parses a `try {...}` expression (`try` token already eaten). - fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> { + fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, Box<Expr>> { let (attrs, body) = self.parse_inner_attrs_and_block(None)?; if self.eat_keyword(exp!(Catch)) { Err(self.dcx().create_err(errors::CatchAfterTry { span: self.prev_token.span })) @@ -3573,7 +3584,7 @@ impl<'a> Parser<'a> { } /// Parses an `async move? {...}` or `gen move? {...}` expression. - fn parse_gen_block(&mut self) -> PResult<'a, P<Expr>> { + fn parse_gen_block(&mut self) -> PResult<'a, Box<Expr>> { let lo = self.token.span; let kind = if self.eat_keyword(exp!(Async)) { if self.eat_keyword(exp!(Gen)) { GenBlockKind::AsyncGen } else { GenBlockKind::Async } @@ -3622,9 +3633,9 @@ impl<'a> Parser<'a> { fn maybe_parse_struct_expr( &mut self, - qself: &Option<P<ast::QSelf>>, + qself: &Option<Box<ast::QSelf>>, path: &ast::Path, - ) -> Option<PResult<'a, P<Expr>>> { + ) -> Option<PResult<'a, Box<Expr>>> { let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL); if struct_allowed || self.is_certainly_not_a_block() { if let Err(err) = self.expect(exp!(OpenBrace)) { @@ -3650,7 +3661,7 @@ impl<'a> Parser<'a> { &mut self, pth: ast::Path, recover: bool, - close: ExpTokenPair<'_>, + close: ExpTokenPair, ) -> PResult< 'a, ( @@ -3669,8 +3680,8 @@ impl<'a> Parser<'a> { errors::HelpUseLatestEdition::new().add_to_diag(e); }; - while self.token != *close.tok { - if self.eat(exp!(DotDot)) || self.recover_struct_field_dots(close.tok) { + while self.token != close.tok { + if self.eat(exp!(DotDot)) || self.recover_struct_field_dots(&close.tok) { let exp_span = self.prev_token.span; // We permit `.. }` on the left-hand side of a destructuring assignment. if self.check(close) { @@ -3818,10 +3829,10 @@ impl<'a> Parser<'a> { /// Precondition: already parsed the '{'. pub(super) fn parse_expr_struct( &mut self, - qself: Option<P<ast::QSelf>>, + qself: Option<Box<ast::QSelf>>, pth: ast::Path, recover: bool, - ) -> PResult<'a, P<Expr>> { + ) -> PResult<'a, Box<Expr>> { let lo = pth.span; let (fields, base, recovered_async) = self.parse_struct_fields(pth.clone(), recover, exp!(CloseBrace))?; @@ -3830,7 +3841,7 @@ impl<'a> Parser<'a> { let expr = if let Some(guar) = recovered_async { ExprKind::Err(guar) } else { - ExprKind::Struct(P(ast::StructExpr { qself, path: pth, fields, rest: base })) + ExprKind::Struct(Box::new(ast::StructExpr { qself, path: pth, fields, rest: base })) }; Ok(self.mk_expr(span, expr)) } @@ -3945,14 +3956,14 @@ impl<'a> Parser<'a> { self.dcx().emit_err(errors::LeftArrowOperator { span }); } - fn mk_assign_op(&self, assign_op: AssignOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind { + fn mk_assign_op(&self, assign_op: AssignOp, lhs: Box<Expr>, rhs: Box<Expr>) -> ExprKind { ExprKind::AssignOp(assign_op, lhs, rhs) } fn mk_range( &mut self, - start: Option<P<Expr>>, - end: Option<P<Expr>>, + start: Option<Box<Expr>>, + end: Option<Box<Expr>>, limits: RangeLimits, ) -> ExprKind { if end.is_none() && limits == RangeLimits::Closed { @@ -3963,51 +3974,56 @@ impl<'a> Parser<'a> { } } - fn mk_unary(&self, unop: UnOp, expr: P<Expr>) -> ExprKind { + fn mk_unary(&self, unop: UnOp, expr: Box<Expr>) -> ExprKind { ExprKind::Unary(unop, expr) } - fn mk_binary(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind { + fn mk_binary(&self, binop: BinOp, lhs: Box<Expr>, rhs: Box<Expr>) -> ExprKind { ExprKind::Binary(binop, lhs, rhs) } - fn mk_index(&self, expr: P<Expr>, idx: P<Expr>, brackets_span: Span) -> ExprKind { + fn mk_index(&self, expr: Box<Expr>, idx: Box<Expr>, brackets_span: Span) -> ExprKind { ExprKind::Index(expr, idx, brackets_span) } - fn mk_call(&self, f: P<Expr>, args: ThinVec<P<Expr>>) -> ExprKind { + fn mk_call(&self, f: Box<Expr>, args: ThinVec<Box<Expr>>) -> ExprKind { ExprKind::Call(f, args) } - fn mk_await_expr(&mut self, self_arg: P<Expr>, lo: Span) -> P<Expr> { + fn mk_await_expr(&mut self, self_arg: Box<Expr>, lo: Span) -> Box<Expr> { let span = lo.to(self.prev_token.span); let await_expr = self.mk_expr(span, ExprKind::Await(self_arg, self.prev_token.span)); self.recover_from_await_method_call(); await_expr } - fn mk_use_expr(&mut self, self_arg: P<Expr>, lo: Span) -> P<Expr> { + fn mk_use_expr(&mut self, self_arg: Box<Expr>, lo: Span) -> Box<Expr> { let span = lo.to(self.prev_token.span); let use_expr = self.mk_expr(span, ExprKind::Use(self_arg, self.prev_token.span)); self.recover_from_use(); use_expr } - pub(crate) fn mk_expr_with_attrs(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> { - P(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None }) + pub(crate) fn mk_expr_with_attrs( + &self, + span: Span, + kind: ExprKind, + attrs: AttrVec, + ) -> Box<Expr> { + Box::new(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None }) } - pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> P<Expr> { + pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> Box<Expr> { self.mk_expr_with_attrs(span, kind, AttrVec::new()) } - pub(super) fn mk_expr_err(&self, span: Span, guar: ErrorGuaranteed) -> P<Expr> { + pub(super) fn mk_expr_err(&self, span: Span, guar: ErrorGuaranteed) -> Box<Expr> { self.mk_expr(span, ExprKind::Err(guar)) } /// Create expression span ensuring the span of the parent node /// is larger than the span of lhs and rhs, including the attributes. - fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, op_span: Span, rhs_span: Span) -> Span { + fn mk_expr_sp(&self, lhs: &Box<Expr>, lhs_span: Span, op_span: Span, rhs_span: Span) -> Span { lhs.attrs .iter() .find(|a| a.style == AttrStyle::Outer) @@ -4019,8 +4035,8 @@ impl<'a> Parser<'a> { fn collect_tokens_for_expr( &mut self, attrs: AttrWrapper, - f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, P<Expr>>, - ) -> PResult<'a, P<Expr>> { + f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, Box<Expr>>, + ) -> PResult<'a, Box<Expr>> { self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { let res = f(this, attrs)?; let trailing = Trailing::from( diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 86326341a75..eb684c3a62f 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -172,8 +172,11 @@ impl<'a> Parser<'a> { }) } - /// Parses a (possibly empty) list of lifetime and type parameters, possibly including - /// a trailing comma and erroneous trailing attributes. + /// Parse a (possibly empty) list of generic (lifetime, type, const) parameters. + /// + /// ```ebnf + /// GenericParams = (GenericParam ("," GenericParam)* ","?)? + /// ``` pub(super) fn parse_generic_params(&mut self) -> PResult<'a, ThinVec<ast::GenericParam>> { let mut params = ThinVec::new(); let mut done = false; @@ -308,9 +311,7 @@ impl<'a> Parser<'a> { /// Parses an experimental fn contract /// (`contract_requires(WWW) contract_ensures(ZZZ)`) - pub(super) fn parse_contract( - &mut self, - ) -> PResult<'a, Option<rustc_ast::ptr::P<ast::FnContract>>> { + pub(super) fn parse_contract(&mut self) -> PResult<'a, Option<Box<ast::FnContract>>> { let requires = if self.eat_keyword_noexpect(exp!(ContractRequires).kw) { self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span); let precond = self.parse_expr()?; @@ -328,7 +329,7 @@ impl<'a> Parser<'a> { if requires.is_none() && ensures.is_none() { Ok(None) } else { - Ok(Some(rustc_ast::ptr::P(ast::FnContract { requires, ensures }))) + Ok(Some(Box::new(ast::FnContract { requires, ensures }))) } } @@ -522,7 +523,7 @@ impl<'a> Parser<'a> { // * `for<'a> Trait1<'a>: Trait2<'a /* ok */>` // * `(for<'a> Trait1<'a>): Trait2<'a /* not ok */>` // * `for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /* ok */, 'b /* not ok */>` - let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?; + let (bound_vars, _) = self.parse_higher_ranked_binder()?; // Parse type with mandatory colon and (possibly empty) bounds, // or with mandatory equality sign and the second type. @@ -530,7 +531,7 @@ impl<'a> Parser<'a> { if self.eat(exp!(Colon)) { let bounds = self.parse_generic_bounds()?; Ok(ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate { - bound_generic_params: lifetime_defs, + bound_generic_params: bound_vars, bounded_ty: ty, bounds, })) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index cb7c5649433..eb264f59fed 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -3,7 +3,6 @@ use std::mem; use ast::token::IdentIsRaw; use rustc_ast::ast::*; -use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::util::case::Case; @@ -44,7 +43,7 @@ impl<'a> Parser<'a> { self.expect(exp!(OpenBrace))?; let (inner_attrs, items, inner_span) = self.parse_mod(exp!(CloseBrace))?; attrs.extend(inner_attrs); - ModKind::Loaded(items, Inline::Yes, inner_span, Ok(())) + ModKind::Loaded(items, Inline::Yes, inner_span) }; Ok(ItemKind::Mod(safety, ident, mod_kind)) } @@ -55,13 +54,13 @@ impl<'a> Parser<'a> { /// - `}` for mod items pub fn parse_mod( &mut self, - term: ExpTokenPair<'_>, - ) -> PResult<'a, (AttrVec, ThinVec<P<Item>>, ModSpans)> { + term: ExpTokenPair, + ) -> PResult<'a, (AttrVec, ThinVec<Box<Item>>, ModSpans)> { let lo = self.token.span; let attrs = self.parse_inner_attributes()?; let post_attr_lo = self.token.span; - let mut items: ThinVec<P<_>> = ThinVec::new(); + let mut items: ThinVec<Box<_>> = ThinVec::new(); // There shouldn't be any stray semicolons before or after items. // `parse_item` consumes the appropriate semicolons so any leftover is an error. @@ -116,9 +115,10 @@ impl<'a> Parser<'a> { } impl<'a> Parser<'a> { - pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<P<Item>>> { - let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; - self.parse_item_(fn_parse_mode, force_collect).map(|i| i.map(P)) + pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Box<Item>>> { + let fn_parse_mode = + FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: true }; + self.parse_item_(fn_parse_mode, force_collect).map(|i| i.map(Box::new)) } fn parse_item_( @@ -327,7 +327,7 @@ impl<'a> Parser<'a> { self.recover_missing_kw_before_item()?; } // MACRO INVOCATION ITEM - ItemKind::MacCall(P(self.parse_item_macro(vis)?)) + ItemKind::MacCall(Box::new(self.parse_item_macro(vis)?)) } else { return Ok(None); }; @@ -664,20 +664,44 @@ impl<'a> Parser<'a> { }; let trait_ref = TraitRef { path, ref_id: ty_first.id }; - (Some(trait_ref), ty_second) + let of_trait = Some(Box::new(TraitImplHeader { + defaultness, + safety, + constness, + polarity, + trait_ref, + })); + (of_trait, ty_second) + } + None => { + let self_ty = ty_first; + let error = |modifier, modifier_name, modifier_span| { + self.dcx().create_err(errors::TraitImplModifierInInherentImpl { + span: self_ty.span, + modifier, + modifier_name, + modifier_span, + self_ty: self_ty.span, + }) + }; + + if let Safety::Unsafe(span) = safety { + error("unsafe", "unsafe", span).with_code(E0197).emit(); + } + if let ImplPolarity::Negative(span) = polarity { + error("!", "negative", span).emit(); + } + if let Defaultness::Default(def_span) = defaultness { + error("default", "default", def_span).emit(); + } + if let Const::Yes(span) = constness { + error("const", "const", span).emit(); + } + (None, self_ty) } - None => (None, ty_first), // impl Type }; - Ok(ItemKind::Impl(Box::new(Impl { - safety, - polarity, - defaultness, - constness, - generics, - of_trait, - self_ty, - items: impl_items, - }))) + + Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items })) } fn parse_item_delegation(&mut self) -> PResult<'a, ItemKind> { @@ -951,17 +975,21 @@ impl<'a> Parser<'a> { pub fn parse_impl_item( &mut self, force_collect: ForceCollect, - ) -> PResult<'a, Option<Option<P<AssocItem>>>> { - let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; + ) -> PResult<'a, Option<Option<Box<AssocItem>>>> { + let fn_parse_mode = + FnParseMode { req_name: |_| true, context: FnContext::Impl, req_body: true }; self.parse_assoc_item(fn_parse_mode, force_collect) } pub fn parse_trait_item( &mut self, force_collect: ForceCollect, - ) -> PResult<'a, Option<Option<P<AssocItem>>>> { - let fn_parse_mode = - FnParseMode { req_name: |edition| edition >= Edition::Edition2018, req_body: false }; + ) -> PResult<'a, Option<Option<Box<AssocItem>>>> { + let fn_parse_mode = FnParseMode { + req_name: |edition| edition >= Edition::Edition2018, + context: FnContext::Trait, + req_body: false, + }; self.parse_assoc_item(fn_parse_mode, force_collect) } @@ -970,7 +998,7 @@ impl<'a> Parser<'a> { &mut self, fn_parse_mode: FnParseMode, force_collect: ForceCollect, - ) -> PResult<'a, Option<Option<P<AssocItem>>>> { + ) -> PResult<'a, Option<Option<Box<AssocItem>>>> { Ok(self.parse_item_(fn_parse_mode, force_collect)?.map( |Item { attrs, id, span, vis, kind, tokens }| { let kind = match AssocItemKind::try_from(kind) { @@ -997,7 +1025,7 @@ impl<'a> Parser<'a> { _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"), }, }; - Some(P(Item { attrs, id, span, vis, kind, tokens })) + Some(Box::new(Item { attrs, id, span, vis, kind, tokens })) }, )) } @@ -1173,7 +1201,7 @@ impl<'a> Parser<'a> { }?; let dash = exp!(Minus); - if self.token != *dash.tok { + if self.token != dash.tok { return Ok(ident); } @@ -1237,8 +1265,9 @@ impl<'a> Parser<'a> { pub fn parse_foreign_item( &mut self, force_collect: ForceCollect, - ) -> PResult<'a, Option<Option<P<ForeignItem>>>> { - let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: false }; + ) -> PResult<'a, Option<Option<Box<ForeignItem>>>> { + let fn_parse_mode = + FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: false }; Ok(self.parse_item_(fn_parse_mode, force_collect)?.map( |Item { attrs, id, span, vis, kind, tokens }| { let kind = match ForeignItemKind::try_from(kind) { @@ -1263,7 +1292,7 @@ impl<'a> Parser<'a> { _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), }, }; - Some(P(Item { attrs, id, span, vis, kind, tokens })) + Some(Box::new(Item { attrs, id, span, vis, kind, tokens })) }, )) } @@ -1365,10 +1394,10 @@ impl<'a> Parser<'a> { }; match &mut item_kind { - ItemKind::Impl(box Impl { of_trait: Some(trai), constness, .. }) => { - *constness = Const::Yes(const_span); + ItemKind::Impl(Impl { of_trait: Some(of_trait), .. }) => { + of_trait.constness = Const::Yes(const_span); - let before_trait = trai.path.span.shrink_to_lo(); + let before_trait = of_trait.trait_ref.path.span.shrink_to_lo(); let const_up_to_impl = const_span.with_hi(impl_span.lo()); err.with_multipart_suggestion( "you might have meant to write a const trait impl", @@ -1424,7 +1453,9 @@ impl<'a> Parser<'a> { /// ```ebnf /// Const = "const" ($ident | "_") Generics ":" $ty (= $expr)? WhereClause ";" ; /// ``` - fn parse_const_item(&mut self) -> PResult<'a, (Ident, Generics, P<Ty>, Option<P<ast::Expr>>)> { + fn parse_const_item( + &mut self, + ) -> PResult<'a, (Ident, Generics, Box<Ty>, Option<Box<ast::Expr>>)> { let ident = self.parse_ident_or_underscore()?; let mut generics = self.parse_generics()?; @@ -1517,7 +1548,7 @@ impl<'a> Parser<'a> { &mut self, colon_present: bool, m: Option<Mutability>, - ) -> P<Ty> { + ) -> Box<Ty> { // Construct the error and stash it away with the hope // that typeck will later enrich the error with a type. let kind = match m { @@ -1537,7 +1568,7 @@ impl<'a> Parser<'a> { // The user intended that the type be inferred, // so treat this as if the user wrote e.g. `const A: _ = expr;`. - P(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID, tokens: None }) + Box::new(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID, tokens: None }) } /// Parses an enum declaration. @@ -2110,7 +2141,8 @@ impl<'a> Parser<'a> { let inherited_vis = Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited, tokens: None }; // We use `parse_fn` to get a span for the function - let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; + let fn_parse_mode = + FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: true }; match self.parse_fn( &mut AttrVec::new(), fn_parse_mode, @@ -2207,7 +2239,7 @@ impl<'a> Parser<'a> { let arrow = TokenTree::token_alone(token::FatArrow, pspan.between(bspan)); // `=>` let tokens = TokenStream::new(vec![params, arrow, body]); let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi()); - P(DelimArgs { dspan, delim: Delimiter::Brace, tokens }) + Box::new(DelimArgs { dspan, delim: Delimiter::Brace, tokens }) } else { self.unexpected_any()? }; @@ -2378,6 +2410,9 @@ pub(crate) struct FnParseMode { /// * The span is from Edition 2015. In particular, you can get a /// 2015 span inside a 2021 crate using macros. pub(super) req_name: ReqName, + /// The context in which this function is parsed, used for diagnostics. + /// This indicates the fn is a free function or method and so on. + pub(super) context: FnContext, /// If this flag is set to `true`, then plain, semicolon-terminated function /// prototypes are not allowed here. /// @@ -2399,6 +2434,18 @@ pub(crate) struct FnParseMode { pub(super) req_body: bool, } +/// The context in which a function is parsed. +/// FIXME(estebank, xizheyin): Use more variants. +#[derive(Clone, Copy, PartialEq, Eq)] +pub(crate) enum FnContext { + /// Free context. + Free, + /// A Trait context. + Trait, + /// An Impl block. + Impl, +} + /// Parsing of functions and methods. impl<'a> Parser<'a> { /// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`. @@ -2409,16 +2456,13 @@ impl<'a> Parser<'a> { sig_lo: Span, vis: &Visibility, case: Case, - ) -> PResult<'a, (Ident, FnSig, Generics, Option<P<FnContract>>, Option<P<Block>>)> { + ) -> PResult<'a, (Ident, FnSig, Generics, Option<Box<FnContract>>, Option<Box<Block>>)> { let fn_span = self.token.span; let header = self.parse_fn_front_matter(vis, case, FrontMatterParsingMode::Function)?; // `const ... fn` let ident = self.parse_ident()?; // `foo` let mut generics = self.parse_generics()?; // `<'a, T, ...>` - let decl = match self.parse_fn_decl( - fn_parse_mode.req_name, - AllowPlus::Yes, - RecoverReturnSign::Yes, - ) { + let decl = match self.parse_fn_decl(&fn_parse_mode, AllowPlus::Yes, RecoverReturnSign::Yes) + { Ok(decl) => decl, Err(old_err) => { // If we see `for Ty ...` then user probably meant `impl` item. @@ -2539,7 +2583,7 @@ impl<'a> Parser<'a> { sig_hi: &mut Span, req_body: bool, fn_params_end: Option<Span>, - ) -> PResult<'a, Option<P<Block>>> { + ) -> PResult<'a, Option<Box<Block>>> { let has_semi = if req_body { self.token == TokenKind::Semi } else { @@ -2936,18 +2980,21 @@ impl<'a> Parser<'a> { /// Parses the parameter list and result type of a function declaration. pub(super) fn parse_fn_decl( &mut self, - req_name: ReqName, + fn_parse_mode: &FnParseMode, ret_allow_plus: AllowPlus, recover_return_sign: RecoverReturnSign, - ) -> PResult<'a, P<FnDecl>> { - Ok(P(FnDecl { - inputs: self.parse_fn_params(req_name)?, + ) -> PResult<'a, Box<FnDecl>> { + Ok(Box::new(FnDecl { + inputs: self.parse_fn_params(fn_parse_mode)?, output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, recover_return_sign)?, })) } /// Parses the parameter list of a function, including the `(` and `)` delimiters. - pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, ThinVec<Param>> { + pub(super) fn parse_fn_params( + &mut self, + fn_parse_mode: &FnParseMode, + ) -> PResult<'a, ThinVec<Param>> { let mut first_param = true; // Parse the arguments, starting out with `self` being allowed... if self.token != TokenKind::OpenParen @@ -2963,7 +3010,7 @@ impl<'a> Parser<'a> { let (mut params, _) = self.parse_paren_comma_seq(|p| { p.recover_vcs_conflict_marker(); let snapshot = p.create_snapshot_for_diagnostic(); - let param = p.parse_param_general(req_name, first_param, true).or_else(|e| { + let param = p.parse_param_general(fn_parse_mode, first_param, true).or_else(|e| { let guar = e.emit(); // When parsing a param failed, we should check to make the span of the param // not contain '(' before it. @@ -2994,7 +3041,7 @@ impl<'a> Parser<'a> { /// - `recover_arg_parse` is used to recover from a failed argument parse. pub(super) fn parse_param_general( &mut self, - req_name: ReqName, + fn_parse_mode: &FnParseMode, first_param: bool, recover_arg_parse: bool, ) -> PResult<'a, Param> { @@ -3010,16 +3057,22 @@ impl<'a> Parser<'a> { let is_name_required = match this.token.kind { token::DotDotDot => false, - _ => req_name(this.token.span.with_neighbor(this.prev_token.span).edition()), + _ => (fn_parse_mode.req_name)( + this.token.span.with_neighbor(this.prev_token.span).edition(), + ), }; let (pat, ty) = if is_name_required || this.is_named_param() { debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); let (pat, colon) = this.parse_fn_param_pat_colon()?; if !colon { let mut err = this.unexpected().unwrap_err(); - return if let Some(ident) = - this.parameter_without_type(&mut err, pat, is_name_required, first_param) - { + return if let Some(ident) = this.parameter_without_type( + &mut err, + pat, + is_name_required, + first_param, + fn_parse_mode, + ) { let guar = err.emit(); Ok((dummy_arg(ident, guar), Trailing::No, UsePreAttrPos::No)) } else { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 90491e53249..15598f32429 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -22,10 +22,9 @@ use std::{fmt, mem, slice}; use attr_wrapper::{AttrWrapper, UsePreAttrPos}; pub use diagnostics::AttemptLocalParseRecovery; pub(crate) use expr::ForbiddenLetReason; -pub(crate) use item::FnParseMode; +pub(crate) use item::{FnContext, FnParseMode}; pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; -use path::PathStyle; -use rustc_ast::ptr::P; +pub use path::PathStyle; use rustc_ast::token::{ self, IdentIsRaw, InvisibleOrigin, MetaVarKind, NtExprKind, NtPatKind, Token, TokenKind, }; @@ -262,19 +261,19 @@ struct CaptureState { /// A sequence separator. #[derive(Debug)] -struct SeqSep<'a> { +struct SeqSep { /// The separator token. - sep: Option<ExpTokenPair<'a>>, + sep: Option<ExpTokenPair>, /// `true` if a trailing separator is allowed. trailing_sep_allowed: bool, } -impl<'a> SeqSep<'a> { - fn trailing_allowed(sep: ExpTokenPair<'a>) -> SeqSep<'a> { +impl SeqSep { + fn trailing_allowed(sep: ExpTokenPair) -> SeqSep { SeqSep { sep: Some(sep), trailing_sep_allowed: true } } - fn none() -> SeqSep<'a> { + fn none() -> SeqSep { SeqSep { sep: None, trailing_sep_allowed: false } } } @@ -286,7 +285,7 @@ pub enum FollowedByType { } #[derive(Copy, Clone, Debug)] -enum Trailing { +pub enum Trailing { No, Yes, } @@ -426,13 +425,13 @@ impl<'a> Parser<'a> { } /// Expects and consumes the token `t`. Signals an error if the next token is not `t`. - pub fn expect(&mut self, exp: ExpTokenPair<'_>) -> PResult<'a, Recovered> { + pub fn expect(&mut self, exp: ExpTokenPair) -> PResult<'a, Recovered> { if self.expected_token_types.is_empty() { - if self.token == *exp.tok { + if self.token == exp.tok { self.bump(); Ok(Recovered::No) } else { - self.unexpected_try_recover(exp.tok) + self.unexpected_try_recover(&exp.tok) } } else { self.expect_one_of(slice::from_ref(&exp), &[]) @@ -444,13 +443,13 @@ impl<'a> Parser<'a> { /// anything. Signal a fatal error if next token is unexpected. fn expect_one_of( &mut self, - edible: &[ExpTokenPair<'_>], - inedible: &[ExpTokenPair<'_>], + edible: &[ExpTokenPair], + inedible: &[ExpTokenPair], ) -> PResult<'a, Recovered> { - if edible.iter().any(|exp| exp.tok == &self.token.kind) { + if edible.iter().any(|exp| exp.tok == self.token.kind) { self.bump(); Ok(Recovered::No) - } else if inedible.iter().any(|exp| exp.tok == &self.token.kind) { + } else if inedible.iter().any(|exp| exp.tok == self.token.kind) { // leave it in the input Ok(Recovered::No) } else if self.token != token::Eof @@ -495,8 +494,8 @@ impl<'a> Parser<'a> { /// This method will automatically add `tok` to `expected_token_types` if `tok` is not /// encountered. #[inline] - fn check(&mut self, exp: ExpTokenPair<'_>) -> bool { - let is_present = self.token == *exp.tok; + pub fn check(&mut self, exp: ExpTokenPair) -> bool { + let is_present = self.token == exp.tok; if !is_present { self.expected_token_types.insert(exp.token_type); } @@ -543,7 +542,7 @@ impl<'a> Parser<'a> { /// Consumes a token 'tok' if it exists. Returns whether the given token was present. #[inline] #[must_use] - pub fn eat(&mut self, exp: ExpTokenPair<'_>) -> bool { + pub fn eat(&mut self, exp: ExpTokenPair) -> bool { let is_present = self.check(exp); if is_present { self.bump() @@ -634,7 +633,7 @@ impl<'a> Parser<'a> { } /// Consume a sequence produced by a metavar expansion, if present. - fn eat_metavar_seq<T>( + pub fn eat_metavar_seq<T>( &mut self, mv_kind: MetaVarKind, f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, @@ -746,13 +745,13 @@ impl<'a> Parser<'a> { /// Eats the expected token if it's present possibly breaking /// compound tokens like multi-character operators in process. /// Returns `true` if the token was eaten. - fn break_and_eat(&mut self, exp: ExpTokenPair<'_>) -> bool { - if self.token == *exp.tok { + fn break_and_eat(&mut self, exp: ExpTokenPair) -> bool { + if self.token == exp.tok { self.bump(); return true; } match self.token.kind.break_two_token_op(1) { - Some((first, second)) if first == *exp.tok => { + Some((first, second)) if first == exp.tok => { let first_span = self.psess.source_map().start_point(self.token.span); let second_span = self.token.span.with_lo(first_span.hi()); self.token = Token::new(first, first_span); @@ -827,7 +826,7 @@ impl<'a> Parser<'a> { /// Checks if the next token is contained within `closes`, and returns `true` if so. fn expect_any_with_type( &mut self, - closes_expected: &[ExpTokenPair<'_>], + closes_expected: &[ExpTokenPair], closes_not_expected: &[&TokenKind], ) -> bool { closes_expected.iter().any(|&close| self.check(close)) @@ -839,9 +838,9 @@ impl<'a> Parser<'a> { /// closing bracket. fn parse_seq_to_before_tokens<T>( &mut self, - closes_expected: &[ExpTokenPair<'_>], + closes_expected: &[ExpTokenPair], closes_not_expected: &[&TokenKind], - sep: SeqSep<'_>, + sep: SeqSep, mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> { let mut first = true; @@ -870,7 +869,7 @@ impl<'a> Parser<'a> { } Err(mut expect_err) => { let sp = self.prev_token.span.shrink_to_hi(); - let token_str = pprust::token_kind_to_string(exp.tok); + let token_str = pprust::token_kind_to_string(&exp.tok); match self.current_closure.take() { Some(closure_spans) if self.token == TokenKind::Semi => { @@ -1040,8 +1039,8 @@ impl<'a> Parser<'a> { /// closing bracket. fn parse_seq_to_before_end<T>( &mut self, - close: ExpTokenPair<'_>, - sep: SeqSep<'_>, + close: ExpTokenPair, + sep: SeqSep, f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> { self.parse_seq_to_before_tokens(&[close], &[], sep, f) @@ -1052,8 +1051,8 @@ impl<'a> Parser<'a> { /// closing bracket. fn parse_seq_to_end<T>( &mut self, - close: ExpTokenPair<'_>, - sep: SeqSep<'_>, + close: ExpTokenPair, + sep: SeqSep, f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, (ThinVec<T>, Trailing)> { let (val, trailing, recovered) = self.parse_seq_to_before_end(close, sep, f)?; @@ -1071,9 +1070,9 @@ impl<'a> Parser<'a> { /// closing bracket. fn parse_unspanned_seq<T>( &mut self, - open: ExpTokenPair<'_>, - close: ExpTokenPair<'_>, - sep: SeqSep<'_>, + open: ExpTokenPair, + close: ExpTokenPair, + sep: SeqSep, f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, (ThinVec<T>, Trailing)> { self.expect(open)?; @@ -1085,8 +1084,8 @@ impl<'a> Parser<'a> { /// closing bracket. fn parse_delim_comma_seq<T>( &mut self, - open: ExpTokenPair<'_>, - close: ExpTokenPair<'_>, + open: ExpTokenPair, + close: ExpTokenPair, f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, (ThinVec<T>, Trailing)> { self.parse_unspanned_seq(open, close, SeqSep::trailing_allowed(exp!(Comma)), f) @@ -1095,7 +1094,7 @@ impl<'a> Parser<'a> { /// Parses a comma-separated sequence delimited by parentheses (e.g. `(x, y)`). /// The function `f` must consume tokens until reaching the next separator or /// closing bracket. - fn parse_paren_comma_seq<T>( + pub fn parse_paren_comma_seq<T>( &mut self, f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, (ThinVec<T>, Trailing)> { @@ -1286,7 +1285,7 @@ impl<'a> Parser<'a> { } /// Parses inline const expressions. - fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P<Expr>> { + fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, Box<Expr>> { self.expect_keyword(exp!(Const))?; let (attrs, blk) = self.parse_inner_attrs_and_block(None)?; let anon_const = AnonConst { @@ -1343,9 +1342,9 @@ impl<'a> Parser<'a> { } } - fn parse_delim_args(&mut self) -> PResult<'a, P<DelimArgs>> { + fn parse_delim_args(&mut self) -> PResult<'a, Box<DelimArgs>> { if let Some(args) = self.parse_delim_args_inner() { - Ok(P(args)) + Ok(Box::new(args)) } else { self.unexpected_any() } @@ -1356,7 +1355,8 @@ impl<'a> Parser<'a> { AttrArgs::Delimited(args) } else if self.eat(exp!(Eq)) { let eq_span = self.prev_token.span; - AttrArgs::Eq { eq_span, expr: self.parse_expr_force_collect()? } + let expr = self.parse_expr_force_collect()?; + AttrArgs::Eq { eq_span, expr } } else { AttrArgs::Empty }) @@ -1389,15 +1389,26 @@ impl<'a> Parser<'a> { // matching `CloseDelim` we are *after* the delimited sequence, // i.e. at depth `d - 1`. let target_depth = self.token_cursor.stack.len() - 1; - loop { - // Advance one token at a time, so `TokenCursor::next()` - // can capture these tokens if necessary. + + if let Capturing::No = self.capture_state.capturing { + // We are not capturing tokens, so skip to the end of the + // delimited sequence. This is a perf win when dealing with + // declarative macros that pass large `tt` fragments through + // multiple rules, as seen in the uom-0.37.0 crate. + self.token_cursor.curr.bump_to_end(); self.bump(); - if self.token_cursor.stack.len() == target_depth { - debug_assert!(self.token.kind.close_delim().is_some()); - break; + debug_assert_eq!(self.token_cursor.stack.len(), target_depth); + } else { + loop { + // Advance one token at a time, so `TokenCursor::next()` + // can capture these tokens if necessary. + self.bump(); + if self.token_cursor.stack.len() == target_depth { + break; + } } } + debug_assert!(self.token.kind.close_delim().is_some()); // Consume close delimiter self.bump(); @@ -1470,7 +1481,7 @@ impl<'a> Parser<'a> { let path = self.parse_path(PathStyle::Mod)?; // `path` self.expect(exp!(CloseParen))?; // `)` let vis = VisibilityKind::Restricted { - path: P(path), + path: Box::new(path), id: ast::DUMMY_NODE_ID, shorthand: false, }; @@ -1487,7 +1498,7 @@ impl<'a> Parser<'a> { let path = self.parse_path(PathStyle::Mod)?; // `crate`/`super`/`self` self.expect(exp!(CloseParen))?; // `)` let vis = VisibilityKind::Restricted { - path: P(path), + path: Box::new(path), id: ast::DUMMY_NODE_ID, shorthand: true, }; @@ -1652,14 +1663,14 @@ pub enum ParseNtResult { Tt(TokenTree), Ident(Ident, IdentIsRaw), Lifetime(Ident, IdentIsRaw), - Item(P<ast::Item>), - Block(P<ast::Block>), - Stmt(P<ast::Stmt>), - Pat(P<ast::Pat>, NtPatKind), - Expr(P<ast::Expr>, NtExprKind), - Literal(P<ast::Expr>), - Ty(P<ast::Ty>), - Meta(P<ast::AttrItem>), - Path(P<ast::Path>), - Vis(P<ast::Visibility>), + Item(Box<ast::Item>), + Block(Box<ast::Block>), + Stmt(Box<ast::Stmt>), + Pat(Box<ast::Pat>, NtPatKind), + Expr(Box<ast::Expr>, NtExprKind), + Literal(Box<ast::Expr>), + Ty(Box<ast::Ty>), + Meta(Box<ast::AttrItem>), + Path(Box<ast::Path>), + Vis(Box<ast::Visibility>), } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 7c83e96c160..42eb07858c2 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -1,4 +1,3 @@ -use rustc_ast::ptr::P; use rustc_ast::token::NtExprKind::*; use rustc_ast::token::NtPatKind::*; use rustc_ast::token::{self, InvisibleOrigin, MetaVarKind, NonterminalKind, Token}; @@ -129,7 +128,7 @@ impl<'a> Parser<'a> { Ok(ParseNtResult::Block(self.collect_tokens_no_attrs(|this| this.parse_block())?)) } NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? { - Some(stmt) => Ok(ParseNtResult::Stmt(P(stmt))), + Some(stmt) => Ok(ParseNtResult::Stmt(Box::new(stmt))), None => { Err(self.dcx().create_err(UnexpectedNonterminal::Statement(self.token.span))) } @@ -170,16 +169,15 @@ impl<'a> Parser<'a> { })) } } - NonterminalKind::Path => Ok(ParseNtResult::Path(P( - self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))? + NonterminalKind::Path => Ok(ParseNtResult::Path(Box::new( + self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?, ))), NonterminalKind::Meta => { - Ok(ParseNtResult::Meta(P(self.parse_attr_item(ForceCollect::Yes)?))) - } - NonterminalKind::Vis => { - Ok(ParseNtResult::Vis(P(self - .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?))) + Ok(ParseNtResult::Meta(Box::new(self.parse_attr_item(ForceCollect::Yes)?))) } + NonterminalKind::Vis => Ok(ParseNtResult::Vis(Box::new( + self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?, + ))), NonterminalKind::Lifetime => { // We want to keep `'keyword` parsing, just like `keyword` is still // an ident for nonterminal purposes. diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 64653ee2a04..9754691a0b9 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1,7 +1,6 @@ use std::ops::Bound; use rustc_ast::mut_visit::{self, MutVisitor}; -use rustc_ast::ptr::P; use rustc_ast::token::NtPatKind::*; use rustc_ast::token::{self, IdentIsRaw, MetaVarKind, Token}; use rustc_ast::util::parser::ExprPrecedence; @@ -25,10 +24,10 @@ use crate::errors::{ GenericArgsInPatRequireTurbofishSyntax, InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern, ParenRangeSuggestion, PatternOnWrongSideOfAt, RemoveLet, RepeatedMutInPattern, SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, - TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed, UnexpectedExpressionInPattern, - UnexpectedExpressionInPatternSugg, UnexpectedLifetimeInPattern, UnexpectedParenInRangePat, - UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam, - UnexpectedVertVertInPattern, WrapInParens, + TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed, TrailingVertSuggestion, + UnexpectedExpressionInPattern, UnexpectedExpressionInPatternSugg, UnexpectedLifetimeInPattern, + UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg, + UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens, }; use crate::parser::expr::{DestructuredFloat, could_be_unclosed_char_literal}; use crate::{exp, maybe_recover_from_interpolated_ty_qpath}; @@ -108,7 +107,7 @@ impl<'a> Parser<'a> { rc: RecoverComma, ra: RecoverColon, rt: CommaRecoveryMode, - ) -> PResult<'a, P<Pat>> { + ) -> PResult<'a, Box<Pat>> { let pat = self.parse_pat_no_top_guard(expected, rc, ra, rt)?; if self.eat_keyword(exp!(If)) { @@ -131,7 +130,7 @@ impl<'a> Parser<'a> { &mut self, expected: Option<Expected>, syntax_loc: Option<PatternLocation>, - ) -> PResult<'a, P<Pat>> { + ) -> PResult<'a, Box<Pat>> { self.parse_pat_with_range_pat(true, expected, syntax_loc) } @@ -150,7 +149,7 @@ impl<'a> Parser<'a> { rc: RecoverComma, ra: RecoverColon, rt: CommaRecoveryMode, - ) -> PResult<'a, P<Pat>> { + ) -> PResult<'a, Box<Pat>> { self.parse_pat_no_top_guard_inner(expected, rc, ra, rt, None).map(|(pat, _)| pat) } @@ -163,7 +162,7 @@ impl<'a> Parser<'a> { ra: RecoverColon, rt: CommaRecoveryMode, syntax_loc: Option<PatternLocation>, - ) -> PResult<'a, (P<Pat>, bool)> { + ) -> PResult<'a, (Box<Pat>, bool)> { // Keep track of whether we recovered from a trailing vert so that we can avoid duplicated // suggestions (which bothers rustfix). // @@ -253,7 +252,7 @@ impl<'a> Parser<'a> { expected: Option<Expected>, rc: RecoverComma, syntax_loc: PatternLocation, - ) -> PResult<'a, (P<Pat>, bool)> { + ) -> PResult<'a, (Box<Pat>, bool)> { // We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level // or-patterns so that we can detect when a user tries to use it. This allows us to print a // better error message. @@ -268,10 +267,9 @@ impl<'a> Parser<'a> { if let PatKind::Or(pats) = &pat.kind { let span = pat.span; - let sub = if pats.len() == 1 { - Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { - span: span.with_hi(span.lo() + BytePos(1)), - }) + let sub = if let [_] = &pats[..] { + let span = span.with_hi(span.lo() + BytePos(1)); + Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span }) } else { Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, @@ -301,7 +299,7 @@ impl<'a> Parser<'a> { /// /// The return value represents the parsed pattern and `true` if a `Colon` was parsed (`false` /// otherwise). - pub(super) fn parse_fn_param_pat_colon(&mut self) -> PResult<'a, (P<Pat>, bool)> { + pub(super) fn parse_fn_param_pat_colon(&mut self) -> PResult<'a, (Box<Pat>, bool)> { // In order to get good UX, we first recover in the case of a leading vert for an illegal // top-level or-pat. Normally, this means recovering both `|` and `||`, but in this case, // a leading `||` probably doesn't indicate an or-pattern attempt, so we handle that @@ -363,6 +361,9 @@ impl<'a> Parser<'a> { self.dcx().emit_err(TrailingVertNotAllowed { span: self.token.span, start: lo, + suggestion: TrailingVertSuggestion { + span: self.prev_token.span.shrink_to_hi().with_hi(self.token.span.hi()), + }, token: self.token, note_double_vert: self.token.kind == token::OrOr, }); @@ -685,7 +686,7 @@ impl<'a> Parser<'a> { PatVisitor { parser: self, stmt, arm: None, field: None }.visit_stmt(stmt); } - fn eat_metavar_pat(&mut self) -> Option<P<Pat>> { + fn eat_metavar_pat(&mut self) -> Option<Box<Pat>> { // Must try both kinds of pattern nonterminals. if let Some(pat) = self.eat_metavar_seq_with_matcher( |mv_kind| matches!(mv_kind, MetaVarKind::Pat(PatParam { .. })), @@ -713,7 +714,7 @@ impl<'a> Parser<'a> { allow_range_pat: bool, expected: Option<Expected>, syntax_loc: Option<PatternLocation>, - ) -> PResult<'a, P<Pat>> { + ) -> PResult<'a, Box<Pat>> { maybe_recover_from_interpolated_ty_qpath!(self, true); if let Some(pat) = self.eat_metavar_pat() { @@ -909,7 +910,7 @@ impl<'a> Parser<'a> { /// e.g. [F#][and] where they are called AND-patterns. /// /// [and]: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching - fn recover_intersection_pat(&mut self, lhs: P<Pat>) -> PResult<'a, P<Pat>> { + fn recover_intersection_pat(&mut self, lhs: Box<Pat>) -> PResult<'a, Box<Pat>> { if self.token != token::At { // Next token is not `@` so it's not going to be an intersection pattern. return Ok(lhs); @@ -1091,7 +1092,7 @@ impl<'a> Parser<'a> { /// Turn all by-value immutable bindings in a pattern into mutable bindings. /// Returns `true` if any change was made. - fn make_all_value_bindings_mutable(pat: &mut P<Pat>) -> bool { + fn make_all_value_bindings_mutable(pat: &mut Box<Pat>) -> bool { struct AddMut(bool); impl MutVisitor for AddMut { fn visit_pat(&mut self, pat: &mut Pat) { @@ -1139,7 +1140,7 @@ impl<'a> Parser<'a> { fn parse_pat_mac_invoc(&mut self, path: Path) -> PResult<'a, PatKind> { self.bump(); let args = self.parse_delim_args()?; - let mac = P(MacCall { path, args }); + let mac = Box::new(MacCall { path, args }); Ok(PatKind::MacCall(mac)) } @@ -1147,7 +1148,7 @@ impl<'a> Parser<'a> { &mut self, err: Diag<'a>, expected: Option<Expected>, - ) -> PResult<'a, P<Pat>> { + ) -> PResult<'a, Box<Pat>> { err.cancel(); let expected = Expected::to_string_or_fallback(expected); @@ -1182,7 +1183,7 @@ impl<'a> Parser<'a> { /// `$begin $form` has already been parsed. fn parse_pat_range_begin_with( &mut self, - begin: P<Expr>, + begin: Box<Expr>, re: Spanned<RangeEnd>, ) -> PResult<'a, PatKind> { let end = if self.is_pat_range_end_start(0) { @@ -1262,7 +1263,7 @@ impl<'a> Parser<'a> { } /// Parse a range pattern end bound - fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> { + fn parse_pat_range_end(&mut self) -> PResult<'a, Box<Expr>> { // recover leading `(` let open_paren = (self.may_recover() && self.eat_noexpect(&token::OpenParen)) .then_some(self.prev_token.span); @@ -1380,7 +1381,7 @@ impl<'a> Parser<'a> { } /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`). - fn parse_pat_struct(&mut self, qself: Option<P<QSelf>>, path: Path) -> PResult<'a, PatKind> { + fn parse_pat_struct(&mut self, qself: Option<Box<QSelf>>, path: Path) -> PResult<'a, PatKind> { if qself.is_some() { // Feature gate the use of qualified paths in patterns self.psess.gated_spans.gate(sym::more_qualified_paths, path.span); @@ -1400,7 +1401,7 @@ impl<'a> Parser<'a> { /// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`). fn parse_pat_tuple_struct( &mut self, - qself: Option<P<QSelf>>, + qself: Option<Box<QSelf>>, path: Path, ) -> PResult<'a, PatKind> { let (fields, _) = self.parse_paren_comma_seq(|p| { @@ -1749,11 +1750,11 @@ impl<'a> Parser<'a> { }) } - pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingMode, ident: Ident) -> P<Pat> { + pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingMode, ident: Ident) -> Box<Pat> { self.mk_pat(span, PatKind::Ident(ann, ident, None)) } - pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> { - P(Pat { kind, span, id: ast::DUMMY_NODE_ID, tokens: None }) + pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> Box<Pat> { + Box::new(Pat { kind, span, id: ast::DUMMY_NODE_ID, tokens: None }) } } diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 8e65ab99c5e..86045648859 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -1,7 +1,6 @@ use std::mem; use ast::token::IdentIsRaw; -use rustc_ast::ptr::P; use rustc_ast::token::{self, MetaVarKind, Token, TokenKind}; use rustc_ast::{ self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemConstraint, @@ -21,11 +20,13 @@ use crate::errors::{ PathFoundAttributeInParams, PathFoundCVariadicParams, PathSingleColon, PathTripleColon, }; use crate::exp; -use crate::parser::{CommaRecoveryMode, ExprKind, RecoverColon, RecoverComma}; +use crate::parser::{ + CommaRecoveryMode, ExprKind, FnContext, FnParseMode, RecoverColon, RecoverComma, +}; /// Specifies how to parse a path. #[derive(Copy, Clone, PartialEq)] -pub(super) enum PathStyle { +pub enum PathStyle { /// In some contexts, notably in expressions, paths with generic arguments are ambiguous /// with something else. For example, in expressions `segment < ....` can be interpreted /// as a comparison and `segment ( ....` can be interpreted as a function call. @@ -75,7 +76,7 @@ impl<'a> Parser<'a> { /// `<T as U>::a` /// `<T as U>::F::a<S>` (without disambiguator) /// `<T as U>::F::a::<S>` (with disambiguator) - pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (P<QSelf>, Path)> { + pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (Box<QSelf>, Path)> { let lo = self.prev_token.span; let ty = self.parse_ty()?; @@ -105,7 +106,7 @@ impl<'a> Parser<'a> { self.expect(exp!(PathSep))?; } - let qself = P(QSelf { ty, path_span, position: path.segments.len() }); + let qself = Box::new(QSelf { ty, path_span, position: path.segments.len() }); if !is_import_coupler { self.parse_path_segments(&mut path.segments, style, None)?; } @@ -149,7 +150,7 @@ impl<'a> Parser<'a> { true } - pub(super) fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> { + pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> { self.parse_path_inner(style, None) } @@ -380,7 +381,7 @@ impl<'a> Parser<'a> { .emit_err(errors::BadReturnTypeNotationOutput { span, suggestion }); } - P(ast::GenericArgs::ParenthesizedElided(span)) + Box::new(ast::GenericArgs::ParenthesizedElided(span)) } else { // `(T, U) -> R` @@ -400,7 +401,13 @@ impl<'a> Parser<'a> { let dcx = self.dcx(); let parse_params_result = self.parse_paren_comma_seq(|p| { - let param = p.parse_param_general(|_| false, false, false); + // Inside parenthesized type arguments, we want types only, not names. + let mode = FnParseMode { + context: FnContext::Free, + req_name: |_| false, + req_body: false, + }; + let param = p.parse_param_general(&mode, false, false); param.map(move |param| { if !matches!(param.pat.kind, PatKind::Missing) { dcx.emit_err(FnPathFoundNamedParams { @@ -842,7 +849,7 @@ impl<'a> Parser<'a> { /// - A literal. /// - A numeric literal prefixed by `-`. /// - A single-segment path. - pub(super) fn expr_is_valid_const_arg(&self, expr: &P<rustc_ast::Expr>) -> bool { + pub(super) fn expr_is_valid_const_arg(&self, expr: &Box<rustc_ast::Expr>) -> bool { match &expr.kind { ast::ExprKind::Block(_, _) | ast::ExprKind::Lit(_) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 2fa6520f2a4..b4943ff7de6 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -4,7 +4,6 @@ use std::ops::Bound; use ast::Label; use rustc_ast as ast; -use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind}; use rustc_ast::util::classify::{self, TrailingBrace}; use rustc_ast::{ @@ -20,8 +19,8 @@ use super::diagnostics::AttemptLocalParseRecovery; use super::pat::{PatternLocation, RecoverComma}; use super::path::PathStyle; use super::{ - AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode, - Trailing, UsePreAttrPos, + AttrWrapper, BlockMode, FnContext, FnParseMode, ForceCollect, Parser, Restrictions, + SemiColonMode, Trailing, UsePreAttrPos, }; use crate::errors::{self, MalformedLoopLabel}; use crate::exp; @@ -154,10 +153,10 @@ impl<'a> Parser<'a> { attrs.clone(), // FIXME: unwanted clone of attrs false, true, - FnParseMode { req_name: |_| true, req_body: true }, + FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: true }, force_collect, )? { - self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))) + self.mk_stmt(lo.to(item.span), StmtKind::Item(Box::new(item))) } else if self.eat(exp!(Semi)) { // Do not attempt to parse an expression if we're done here. self.error_outer_attrs(attrs); @@ -246,7 +245,7 @@ impl<'a> Parser<'a> { _ => MacStmtStyle::NoBraces, }; - let mac = P(MacCall { path, args }); + let mac = Box::new(MacCall { path, args }); let kind = if (style == MacStmtStyle::Braces && !matches!(self.token.kind, token::Dot | token::Question)) @@ -256,7 +255,7 @@ impl<'a> Parser<'a> { | token::Eof | token::CloseInvisible(InvisibleOrigin::MetaVar(MetaVarKind::Stmt)) ) { - StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None })) + StmtKind::MacCall(Box::new(MacCallStmt { mac, style, attrs, tokens: None })) } else { // Since none of the above applied, this is an expression statement macro. let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac)); @@ -307,7 +306,7 @@ impl<'a> Parser<'a> { } /// Parses a local variable declaration. - fn parse_local(&mut self, super_: Option<Span>, attrs: AttrVec) -> PResult<'a, P<Local>> { + fn parse_local(&mut self, super_: Option<Span>, attrs: AttrVec) -> PResult<'a, Box<Local>> { let lo = super_.unwrap_or(self.prev_token.span); if self.token.is_keyword(kw::Const) && self.look_ahead(1, |t| t.is_ident()) { @@ -409,7 +408,7 @@ impl<'a> Parser<'a> { } }; let hi = if self.token == token::Semi { self.token.span } else { self.prev_token.span }; - Ok(P(ast::Local { + Ok(Box::new(ast::Local { super_, ty, pat, @@ -463,7 +462,7 @@ impl<'a> Parser<'a> { } /// Parses the RHS of a local variable declaration (e.g., `= 14;`). - fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option<P<Expr>>> { + fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option<Box<Expr>>> { let eq_consumed = match self.token.kind { token::PlusEq | token::MinusEq @@ -494,7 +493,7 @@ impl<'a> Parser<'a> { } /// Parses a block. No inner attributes are allowed. - pub fn parse_block(&mut self) -> PResult<'a, P<Block>> { + pub fn parse_block(&mut self) -> PResult<'a, Box<Block>> { let (attrs, block) = self.parse_inner_attrs_and_block(None)?; if let [.., last] = &*attrs { let suggest_to_outer = match &last.kind { @@ -679,7 +678,7 @@ impl<'a> Parser<'a> { pub(super) fn parse_inner_attrs_and_block( &mut self, loop_header: Option<Span>, - ) -> PResult<'a, (AttrVec, P<Block>)> { + ) -> PResult<'a, (AttrVec, Box<Block>)> { self.parse_block_common(self.token.span, BlockCheckMode::Default, loop_header) } @@ -692,7 +691,7 @@ impl<'a> Parser<'a> { lo: Span, blk_mode: BlockCheckMode, loop_header: Option<Span>, - ) -> PResult<'a, (AttrVec, P<Block>)> { + ) -> PResult<'a, (AttrVec, Box<Block>)> { if let Some(block) = self.eat_metavar_seq(MetaVarKind::Block, |this| this.parse_block()) { return Ok((AttrVec::new(), block)); } @@ -718,7 +717,7 @@ impl<'a> Parser<'a> { lo: Span, s: BlockCheckMode, recover: AttemptLocalParseRecovery, - ) -> PResult<'a, P<Block>> { + ) -> PResult<'a, Box<Block>> { let mut stmts = ThinVec::new(); let mut snapshot = None; while !self.eat(exp!(CloseBrace)) { @@ -1050,8 +1049,8 @@ impl<'a> Parser<'a> { stmts: ThinVec<Stmt>, rules: BlockCheckMode, span: Span, - ) -> P<Block> { - P(Block { stmts, id: DUMMY_NODE_ID, rules, span, tokens: None }) + ) -> Box<Block> { + Box::new(Block { stmts, id: DUMMY_NODE_ID, rules, span, tokens: None }) } pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt { @@ -1062,7 +1061,7 @@ impl<'a> Parser<'a> { self.mk_stmt(span, StmtKind::Expr(self.mk_expr_err(span, guar))) } - pub(super) fn mk_block_err(&self, span: Span, guar: ErrorGuaranteed) -> P<Block> { + pub(super) fn mk_block_err(&self, span: Span, guar: ErrorGuaranteed) -> Box<Block> { self.mk_block(thin_vec![self.mk_stmt_err(span, guar)], BlockCheckMode::Default, span) } } diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 43a1d779a75..a6e7266e71b 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -8,7 +8,6 @@ use std::sync::{Arc, Mutex}; use std::{io, str}; use ast::token::IdentIsRaw; -use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token}; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_ast::{self as ast, PatKind, visit}; @@ -2240,7 +2239,7 @@ fn parse_item_from_source_str( name: FileName, source: String, psess: &ParseSess, -) -> PResult<'_, Option<P<ast::Item>>> { +) -> PResult<'_, Option<Box<ast::Item>>> { unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source)) .parse_item(ForceCollect::No) } @@ -2251,12 +2250,12 @@ fn sp(a: u32, b: u32) -> Span { } /// Parses a string, return an expression. -fn string_to_expr(source_str: String) -> P<ast::Expr> { +fn string_to_expr(source_str: String) -> Box<ast::Expr> { with_error_checking_parse(source_str, &psess(), |p| p.parse_expr()) } /// Parses a string, returns an item. -fn string_to_item(source_str: String) -> Option<P<ast::Item>> { +fn string_to_item(source_str: String) -> Option<Box<ast::Item>> { with_error_checking_parse(source_str, &psess(), |p| p.parse_item(ForceCollect::No)) } @@ -2520,7 +2519,7 @@ fn ttdelim_span() { name: FileName, source: String, psess: &ParseSess, - ) -> PResult<'_, P<ast::Expr>> { + ) -> PResult<'_, Box<ast::Expr>> { unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source)).parse_expr() } diff --git a/compiler/rustc_parse/src/parser/token_type.rs b/compiler/rustc_parse/src/parser/token_type.rs index b91548196a3..bd4bb368df0 100644 --- a/compiler/rustc_parse/src/parser/token_type.rs +++ b/compiler/rustc_parse/src/parser/token_type.rs @@ -416,8 +416,8 @@ impl TokenType { /// is always by used those methods. The second field is only used when the /// first field doesn't match. #[derive(Clone, Copy, Debug)] -pub struct ExpTokenPair<'a> { - pub tok: &'a TokenKind, +pub struct ExpTokenPair { + pub tok: TokenKind, pub token_type: TokenType, } @@ -444,7 +444,7 @@ macro_rules! exp { // `ExpTokenPair` helper rules. (@tok, $tok:ident) => { $crate::parser::token_type::ExpTokenPair { - tok: &rustc_ast::token::$tok, + tok: rustc_ast::token::$tok, token_type: $crate::parser::token_type::TokenType::$tok } }; diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 59048e42e6f..6168647183f 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1,4 +1,3 @@ -use rustc_ast::ptr::P; use rustc_ast::token::{self, IdentIsRaw, MetaVarKind, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::{ @@ -20,6 +19,7 @@ use crate::errors::{ NestedCVariadicType, ReturnTypesUseThinArrow, }; use crate::parser::item::FrontMatterParsingMode; +use crate::parser::{FnContext, FnParseMode}; use crate::{exp, maybe_recover_from_interpolated_ty_qpath}; /// Signals whether parsing a type should allow `+`. @@ -105,7 +105,7 @@ fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool { impl<'a> Parser<'a> { /// Parses a type. - pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> { + pub fn parse_ty(&mut self) -> PResult<'a, Box<Ty>> { // Make sure deeply nested types don't overflow the stack. ensure_sufficient_stack(|| { self.parse_ty_common( @@ -122,7 +122,7 @@ impl<'a> Parser<'a> { pub(super) fn parse_ty_with_generics_recovery( &mut self, ty_params: &Generics, - ) -> PResult<'a, P<Ty>> { + ) -> PResult<'a, Box<Ty>> { self.parse_ty_common( AllowPlus::Yes, AllowCVariadic::No, @@ -136,15 +136,38 @@ impl<'a> Parser<'a> { /// Parse a type suitable for a function or function pointer parameter. /// The difference from `parse_ty` is that this version allows `...` /// (`CVarArgs`) at the top level of the type. - pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> { - self.parse_ty_common( + pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, Box<Ty>> { + let ty = self.parse_ty_common( AllowPlus::Yes, AllowCVariadic::Yes, RecoverQPath::Yes, RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, - ) + )?; + + // Recover a trailing `= EXPR` if present. + if self.may_recover() + && self.check_noexpect(&token::Eq) + && self.look_ahead(1, |tok| tok.can_begin_expr()) + { + let snapshot = self.create_snapshot_for_diagnostic(); + self.bump(); + let eq_span = self.prev_token.span; + match self.parse_expr() { + Ok(e) => { + self.dcx() + .struct_span_err(eq_span.to(e.span), "parameter defaults are not supported") + .emit(); + } + Err(diag) => { + diag.cancel(); + self.restore_snapshot(snapshot); + } + } + } + + Ok(ty) } /// Parses a type in restricted contexts where `+` is not permitted. @@ -153,7 +176,7 @@ impl<'a> Parser<'a> { /// `+` is prohibited to maintain operator priority (P(+) < P(&)). /// Example 2: `value1 as TYPE + value2` /// `+` is prohibited to avoid interactions with expression grammar. - pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> { + pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, Box<Ty>> { self.parse_ty_common( AllowPlus::No, AllowCVariadic::No, @@ -166,7 +189,7 @@ impl<'a> Parser<'a> { /// Parses a type following an `as` cast. Similar to `parse_ty_no_plus`, but signaling origin /// for better diagnostics involving `?`. - pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, P<Ty>> { + pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, Box<Ty>> { self.parse_ty_common( AllowPlus::No, AllowCVariadic::No, @@ -177,7 +200,7 @@ impl<'a> Parser<'a> { ) } - pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> { + pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, Box<Ty>> { self.parse_ty_common( AllowPlus::Yes, AllowCVariadic::No, @@ -190,7 +213,7 @@ impl<'a> Parser<'a> { /// Parse a type without recovering `:` as `->` to avoid breaking code such /// as `where fn() : for<'a>`. - pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> { + pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, Box<Ty>> { self.parse_ty_common( AllowPlus::Yes, AllowCVariadic::No, @@ -250,7 +273,7 @@ impl<'a> Parser<'a> { recover_return_sign: RecoverReturnSign, ty_generics: Option<&Generics>, recover_question_mark: RecoverQuestionMark, - ) -> PResult<'a, P<Ty>> { + ) -> PResult<'a, Box<Ty>> { let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes; maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) { @@ -308,11 +331,11 @@ impl<'a> Parser<'a> { // Function pointer type or bound list (trait object type) starting with a poly-trait. // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T` // `for<'lt> Trait1<'lt> + Trait2 + 'a` - let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?; + let (bound_vars, _) = self.parse_higher_ranked_binder()?; if self.check_fn_front_matter(false, Case::Sensitive) { self.parse_ty_fn_ptr( lo, - lifetime_defs, + bound_vars, Some(self.prev_token.span.shrink_to_lo()), recover_return_sign, )? @@ -326,7 +349,7 @@ impl<'a> Parser<'a> { let path = self.parse_path(PathStyle::Type)?; let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus(); let kind = self.parse_remaining_bounds_path( - lifetime_defs, + bound_vars, path, lo, parse_plus, @@ -359,7 +382,7 @@ impl<'a> Parser<'a> { let path = self.parse_path(PathStyle::Type)?; let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus(); self.parse_remaining_bounds_path( - lifetime_defs, + bound_vars, path, lo, parse_plus, @@ -425,7 +448,7 @@ impl<'a> Parser<'a> { let span = lo.to(self.prev_token.span); self.psess.gated_spans.gate(sym::unsafe_binders, span); - Ok(TyKind::UnsafeBinder(P(UnsafeBinderTy { generic_params, inner_ty }))) + Ok(TyKind::UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, inner_ty }))) } /// Parses either: @@ -443,7 +466,7 @@ impl<'a> Parser<'a> { let ty = ts.into_iter().next().unwrap(); let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus(); match ty.kind { - // `(TY_BOUND_NOPAREN) + BOUND + ...`. + // `"(" BareTraitBound ")" "+" Bound "+" ...`. TyKind::Path(None, path) if maybe_bounds => self.parse_remaining_bounds_path( ThinVec::new(), path, @@ -610,7 +633,7 @@ impl<'a> Parser<'a> { /// - `[u8, 5]` → suggests using `;`, return a Array type /// - `[u8 5]` → suggests using `;`, return a Array type /// Consider to add more cases in the future. - fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: P<Ty>) -> PResult<'a, TyKind> { + fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: Box<Ty>) -> PResult<'a, TyKind> { let span = self.token.span; let token_descr = super::token_descr(&self.token); let mut err = @@ -770,10 +793,21 @@ impl<'a> Parser<'a> { if self.may_recover() && self.token == TokenKind::Lt { self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?; } - let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?; + let mode = crate::parser::item::FnParseMode { + req_name: |_| false, + context: FnContext::Free, + req_body: false, + }; + let decl = self.parse_fn_decl(&mode, AllowPlus::No, recover_return_sign)?; let decl_span = span_start.to(self.prev_token.span); - Ok(TyKind::FnPtr(P(FnPtrTy { ext, safety, generic_params: params, decl, decl_span }))) + Ok(TyKind::FnPtr(Box::new(FnPtrTy { + ext, + safety, + generic_params: params, + decl, + decl_span, + }))) } /// Recover from function pointer types with a generic parameter list (e.g. `fn<'a>(&'a str)`). @@ -842,10 +876,13 @@ impl<'a> Parser<'a> { Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)) } - fn parse_precise_capturing_args( - &mut self, - ) -> PResult<'a, (ThinVec<PreciseCapturingArg>, Span)> { - let lo = self.token.span; + /// Parse a use-bound aka precise capturing list. + /// + /// ```ebnf + /// UseBound = "use" "<" (PreciseCapture ("," PreciseCapture)* ","?)? ">" + /// PreciseCapture = "Self" | Ident | Lifetime + /// ``` + fn parse_use_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> { self.expect_lt()?; let (args, _, _) = self.parse_seq_to_before_tokens( &[exp!(Gt)], @@ -871,7 +908,13 @@ impl<'a> Parser<'a> { }, )?; self.expect_gt()?; - Ok((args, lo.to(self.prev_token.span))) + + if let ast::Parens::Yes = parens { + self.expect(exp!(CloseParen))?; + self.report_parenthesized_bound(lo, self.prev_token.span, "precise capturing lists"); + } + + Ok(GenericBound::Use(args, lo.to(self.prev_token.span))) } /// Is a `dyn B0 + ... + Bn` type allowed here? @@ -915,7 +958,7 @@ impl<'a> Parser<'a> { let path = self.parse_path_inner(PathStyle::Type, ty_generics)?; if self.eat(exp!(Bang)) { // Macro invocation in type position - Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_delim_args()? }))) + Ok(TyKind::MacCall(Box::new(MacCall { path, args: self.parse_delim_args()? }))) } else if allow_plus == AllowPlus::Yes && self.check_plus() { // `Trait1 + Trait2 + 'a` self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true, ast::Parens::No) @@ -929,9 +972,10 @@ impl<'a> Parser<'a> { self.parse_generic_bounds_common(AllowPlus::Yes) } - /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`. + /// Parse generic bounds. /// - /// See `parse_generic_bound` for the `BOUND` grammar. + /// Only if `allow_plus` this parses a `+`-separated list of bounds (trailing `+` is admitted). + /// Otherwise, this only parses a single bound or none. fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> { let mut bounds = Vec::new(); @@ -977,48 +1021,56 @@ impl<'a> Parser<'a> { || self.check_keyword(exp!(Use)) } - /// Parses a bound according to the grammar: + /// Parse a bound. + /// /// ```ebnf - /// BOUND = TY_BOUND | LT_BOUND + /// Bound = LifetimeBound | UseBound | TraitBound /// ``` fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> { - let lo = self.token.span; let leading_token = self.prev_token; + let lo = self.token.span; + + // We only admit parenthesized *trait* bounds. However, we want to gracefully recover from + // other kinds of parenthesized bounds, so parse the opening parenthesis *here*. + // + // In the future we might want to lift this syntactic restriction and + // introduce "`GenericBound::Paren(Box<GenericBound>)`". let parens = if self.eat(exp!(OpenParen)) { ast::Parens::Yes } else { ast::Parens::No }; - let bound = if self.token.is_lifetime() { - self.parse_generic_lt_bound(lo, parens)? + if self.token.is_lifetime() { + self.parse_lifetime_bound(lo, parens) } else if self.eat_keyword(exp!(Use)) { - // parse precise captures, if any. This is `use<'lt, 'lt, P, P>`; a list of - // lifetimes and ident params (including SelfUpper). These are validated later - // for order, duplication, and whether they actually reference params. - let use_span = self.prev_token.span; - let (args, args_span) = self.parse_precise_capturing_args()?; - GenericBound::Use(args, use_span.to(args_span)) + self.parse_use_bound(lo, parens) } else { - self.parse_generic_ty_bound(lo, parens, &leading_token)? - }; - - Ok(bound) + self.parse_trait_bound(lo, parens, &leading_token) + } } - /// Parses a lifetime ("outlives") bound, e.g. `'a`, according to: + /// Parse a lifetime-bound aka outlives-bound. + /// /// ```ebnf - /// LT_BOUND = LIFETIME + /// LifetimeBound = Lifetime /// ``` - fn parse_generic_lt_bound( - &mut self, - lo: Span, - parens: ast::Parens, - ) -> PResult<'a, GenericBound> { + fn parse_lifetime_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> { let lt = self.expect_lifetime(); - let bound = GenericBound::Outlives(lt); + if let ast::Parens::Yes = parens { - // FIXME(Centril): Consider not erroring here and accepting `('lt)` instead, - // possibly introducing `GenericBound::Paren(P<GenericBound>)`? - self.recover_paren_lifetime(lo)?; + self.expect(exp!(CloseParen))?; + self.report_parenthesized_bound(lo, self.prev_token.span, "lifetime bounds"); } - Ok(bound) + + Ok(GenericBound::Outlives(lt)) + } + + fn report_parenthesized_bound(&self, lo: Span, hi: Span, kind: &str) -> ErrorGuaranteed { + let mut diag = + self.dcx().struct_span_err(lo.to(hi), format!("{kind} may not be parenthesized")); + diag.multipart_suggestion( + "remove the parentheses", + vec![(lo, String::new()), (hi, String::new())], + Applicability::MachineApplicable, + ); + diag.emit() } /// Emits an error if any trait bound modifiers were present. @@ -1063,27 +1115,17 @@ impl<'a> Parser<'a> { unreachable!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?") } - /// Recover on `('lifetime)` with `(` already eaten. - fn recover_paren_lifetime(&mut self, lo: Span) -> PResult<'a, ()> { - self.expect(exp!(CloseParen))?; - let span = lo.to(self.prev_token.span); - let sugg = errors::RemoveParens { lo, hi: self.prev_token.span }; - - self.dcx().emit_err(errors::ParenthesizedLifetime { span, sugg }); - Ok(()) - } - /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `[const] Trait`. /// /// If no modifiers are present, this does not consume any tokens. /// /// ```ebnf - /// CONSTNESS = [["["] "const" ["]"]] - /// ASYNCNESS = ["async"] - /// POLARITY = ["?" | "!"] + /// Constness = ("const" | "[" "const" "]")? + /// Asyncness = "async"? + /// Polarity = ("?" | "!")? /// ``` /// - /// See `parse_generic_ty_bound` for the complete grammar of trait bound modifiers. + /// See `parse_trait_bound` for more context. fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> { let modifier_lo = self.token.span; let constness = self.parse_bound_constness()?; @@ -1176,20 +1218,21 @@ impl<'a> Parser<'a> { }) } - /// Parses a type bound according to: + /// Parse a trait bound. + /// /// ```ebnf - /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) - /// TY_BOUND_NOPAREN = [for<GENERIC_PARAMS> CONSTNESS ASYNCNESS | POLARITY] SIMPLE_PATH + /// TraitBound = BareTraitBound | "(" BareTraitBound ")" + /// BareTraitBound = + /// (HigherRankedBinder Constness Asyncness | Polarity) + /// TypePath /// ``` - /// - /// For example, this grammar accepts `for<'a: 'b> [const] ?m::Trait<'a>`. - fn parse_generic_ty_bound( + fn parse_trait_bound( &mut self, lo: Span, parens: ast::Parens, leading_token: &Token, ) -> PResult<'a, GenericBound> { - let (mut lifetime_defs, binder_span) = self.parse_late_bound_lifetime_defs()?; + let (mut bound_vars, binder_span) = self.parse_higher_ranked_binder()?; let modifiers_lo = self.token.span; let modifiers = self.parse_trait_bound_modifiers()?; @@ -1212,11 +1255,11 @@ impl<'a> Parser<'a> { // e.g. `T: for<'a> 'a` or `T: [const] 'a`. if self.token.is_lifetime() { let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span); - return self.parse_generic_lt_bound(lo, parens); + return self.parse_lifetime_bound(lo, parens); } - if let (more_lifetime_defs, Some(binder_span)) = self.parse_late_bound_lifetime_defs()? { - lifetime_defs.extend(more_lifetime_defs); + if let (more_bound_vars, Some(binder_span)) = self.parse_higher_ranked_binder()? { + bound_vars.extend(more_bound_vars); self.dcx().emit_err(errors::BinderBeforeModifiers { binder_span, modifiers_span }); } @@ -1276,7 +1319,7 @@ impl<'a> Parser<'a> { }; if self.may_recover() && self.token == TokenKind::OpenParen { - self.recover_fn_trait_with_lifetime_params(&mut path, &mut lifetime_defs)?; + self.recover_fn_trait_with_lifetime_params(&mut path, &mut bound_vars)?; } if let ast::Parens::Yes = parens { @@ -1299,7 +1342,7 @@ impl<'a> Parser<'a> { } let poly_trait = - PolyTraitRef::new(lifetime_defs, path, modifiers, lo.to(self.prev_token.span), parens); + PolyTraitRef::new(bound_vars, path, modifiers, lo.to(self.prev_token.span), parens); Ok(GenericBound::Trait(poly_trait)) } @@ -1309,7 +1352,8 @@ impl<'a> Parser<'a> { self.bump(); let args_lo = self.token.span; let snapshot = self.create_snapshot_for_diagnostic(); - match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) { + let mode = FnParseMode { req_name: |_| false, context: FnContext::Free, req_body: false }; + match self.parse_fn_decl(&mode, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) { Ok(decl) => { self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span }); Some(ast::Path { @@ -1317,12 +1361,14 @@ impl<'a> Parser<'a> { segments: thin_vec![ast::PathSegment { ident: Ident::new(sym::Fn, fn_token_span), id: DUMMY_NODE_ID, - args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs { - span: args_lo.to(self.prev_token.span), - inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(), - inputs_span: args_lo.until(decl.output.span()), - output: decl.output.clone(), - }))), + args: Some(Box::new(ast::GenericArgs::Parenthesized( + ast::ParenthesizedArgs { + span: args_lo.to(self.prev_token.span), + inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(), + inputs_span: args_lo.until(decl.output.span()), + output: decl.output.clone(), + } + ))), }], tokens: None, }) @@ -1335,8 +1381,12 @@ impl<'a> Parser<'a> { } } - /// Optionally parses `for<$generic_params>`. - pub(super) fn parse_late_bound_lifetime_defs( + /// Parse an optional higher-ranked binder. + /// + /// ```ebnf + /// HigherRankedBinder = ("for" "<" GenericParams ">")? + /// ``` + pub(super) fn parse_higher_ranked_binder( &mut self, ) -> PResult<'a, (ThinVec<GenericParam>, Option<Span>)> { if self.eat_keyword(exp!(For)) { @@ -1393,8 +1443,9 @@ impl<'a> Parser<'a> { // Parse `(T, U) -> R`. let inputs_lo = self.token.span; + let mode = FnParseMode { req_name: |_| false, context: FnContext::Free, req_body: false }; let inputs: ThinVec<_> = - self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect(); + self.parse_fn_params(&mode)?.into_iter().map(|input| input.ty).collect(); let inputs_span = inputs_lo.to(self.prev_token.span); let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?; let args = ast::ParenthesizedArgs { @@ -1451,8 +1502,7 @@ impl<'a> Parser<'a> { pub(super) fn expect_lifetime(&mut self) -> Lifetime { if let Some((ident, is_raw)) = self.token.lifetime() { if matches!(is_raw, IdentIsRaw::No) - && ident.without_first_quote().is_reserved() - && ![kw::UnderscoreLifetime, kw::StaticLifetime].contains(&ident.name) + && ident.without_first_quote().is_reserved_lifetime() { self.dcx().emit_err(errors::KeywordLifetime { span: ident.span }); } @@ -1464,7 +1514,7 @@ impl<'a> Parser<'a> { } } - pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> P<Ty> { - P(Ty { kind, span, id: ast::DUMMY_NODE_ID, tokens: None }) + pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> Box<Ty> { + Box::new(Ty { kind, span, id: ast::DUMMY_NODE_ID, tokens: None }) } } |
