From ddcd7cac41b05995426b97f0f0bbca0866a1dd96 Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 14 Aug 2023 17:51:19 +0800 Subject: Fix bad suggestion when wrong parentheses around a dyn trait --- compiler/rustc_parse/src/parser/ty.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 3bb50b05aa3..27b1e9c0f11 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -714,6 +714,7 @@ impl<'a> Parser<'a> { /// ``` fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> { let lo = self.token.span; + let leading_token = self.prev_token.clone(); let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis)); let inner_lo = self.token.span; @@ -722,7 +723,7 @@ impl<'a> Parser<'a> { self.error_lt_bound_with_modifiers(modifiers); self.parse_generic_lt_bound(lo, inner_lo, has_parens)? } else { - self.parse_generic_ty_bound(lo, has_parens, modifiers)? + self.parse_generic_ty_bound(lo, has_parens, modifiers, &leading_token)? }; Ok(bound) @@ -827,6 +828,7 @@ impl<'a> Parser<'a> { lo: Span, has_parens: bool, modifiers: BoundModifiers, + leading_token: &Token, ) -> PResult<'a, GenericBound> { let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?; let mut path = if self.token.is_keyword(kw::Fn) @@ -873,18 +875,18 @@ impl<'a> Parser<'a> { } if has_parens { - if self.token.is_like_plus() { - // Someone has written something like `&dyn (Trait + Other)`. The correct code - // would be `&(dyn Trait + Other)`, but we don't have access to the appropriate - // span to suggest that. When written as `&dyn Trait + Other`, an appropriate - // suggestion is given. + // Someone has written something like `&dyn (Trait + Other)`. The correct code + // would be `&(dyn Trait + Other)` + if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) { let bounds = vec![]; self.parse_remaining_bounds(bounds, true)?; self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; - let sp = vec![lo, self.prev_token.span]; - self.sess.emit_err(errors::IncorrectBracesTraitBounds { - span: sp, - sugg: errors::IncorrectBracesTraitBoundsSugg { l: lo, r: self.prev_token.span }, + self.sess.emit_err(errors::IncorrectParensTraitBounds { + span: vec![lo, self.prev_token.span], + sugg: errors::IncorrectParensTraitBoundsSugg { + wrong_span: leading_token.span.shrink_to_hi().to(lo), + new_span: leading_token.span.shrink_to_lo(), + }, }); } else { self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; -- cgit 1.4.1-3-g733a5 From 434bfc316293a1b2c959e4f8c8facb1634abf729 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Aug 2023 11:02:35 +1000 Subject: Remove outdated comment. All nonterminals collect and store tokens now. (Unless they are very simple, e.g. single-token, and can precisely recover them without collecting.) --- compiler/rustc_parse/src/parser/nonterminal.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index f5681532b3a..7e1a2b6a306 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -101,8 +101,6 @@ impl<'a> Parser<'a> { /// site. #[inline] pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt> { - // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`) - // needs to have them force-captured here. // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro, // which requires having captured tokens available. Since we cannot determine // in advance whether or not a proc-macro will be (transitively) invoked, -- cgit 1.4.1-3-g733a5 From 04cf6b4ac56ee72b6621b82a01074607da70f04b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 9 Aug 2023 12:57:05 +1000 Subject: Rename `parse_no_question_mark_recover`. Adding a `ty_` makes its purpose much clearer, and consistent with other `parse_ty_*` functions. --- compiler/rustc_parse/src/parser/nonterminal.rs | 2 +- compiler/rustc_parse/src/parser/ty.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 7e1a2b6a306..7fb517ffdb8 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -149,7 +149,7 @@ impl<'a> Parser<'a> { } NonterminalKind::Ty => token::NtTy( - self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?, + self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?, ), // this could be handled like a token, since it is one diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 3bb50b05aa3..88e640f1696 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -180,7 +180,7 @@ impl<'a> Parser<'a> { ) } - pub(super) fn parse_no_question_mark_recover(&mut self) -> PResult<'a, P> { + pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, P> { self.parse_ty_common( AllowPlus::Yes, AllowCVariadic::No, -- cgit 1.4.1-3-g733a5 From e8f733370f45dca86356a7358642702c7438fca8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 9 Aug 2023 15:02:30 +1000 Subject: Add some useful comments to `Parser::look_ahead`. --- compiler/rustc_parse/src/parser/mod.rs | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index ce4d4a60551..3c3872f2706 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1052,33 +1052,48 @@ impl<'a> Parser<'a> { } /// Look-ahead `dist` tokens of `self.token` and get access to that token there. - /// When `dist == 0` then the current token is looked at. + /// When `dist == 0` then the current token is looked at. `Eof` will be + /// returned if the look-ahead is any distance past the end of the tokens. pub fn look_ahead(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R { if dist == 0 { return looker(&self.token); } - let tree_cursor = &self.token_cursor.tree_cursor; if let Some(&(_, delim, span)) = self.token_cursor.stack.last() && delim != Delimiter::Invisible { + // We are not in the outermost token stream, and the token stream + // we are in has non-skipped delimiters. Look for skipped + // delimiters in the lookahead range. + let tree_cursor = &self.token_cursor.tree_cursor; let all_normal = (0..dist).all(|i| { let token = tree_cursor.look_ahead(i); !matches!(token, Some(TokenTree::Delimited(_, Delimiter::Invisible, _))) }); if all_normal { + // There were no skipped delimiters. Do lookahead by plain indexing. return match tree_cursor.look_ahead(dist - 1) { - Some(tree) => match tree { - TokenTree::Token(token, _) => looker(token), - TokenTree::Delimited(dspan, delim, _) => { - looker(&Token::new(token::OpenDelim(*delim), dspan.open)) + Some(tree) => { + // Indexing stayed within the current token stream. + match tree { + TokenTree::Token(token, _) => looker(token), + TokenTree::Delimited(dspan, delim, _) => { + looker(&Token::new(token::OpenDelim(*delim), dspan.open)) + } } - }, - None => looker(&Token::new(token::CloseDelim(delim), span.close)), + } + None => { + // Indexing went past the end of the current token + // stream. Use the close delimiter, no matter how far + // ahead `dist` went. + looker(&Token::new(token::CloseDelim(delim), span.close)) + } }; } } + // We are in a more complex case. Just clone the token cursor and use + // `next`, skipping delimiters as necessary. Slow but simple. let mut cursor = self.token_cursor.clone(); let mut i = 0; let mut token = Token::dummy(); -- cgit 1.4.1-3-g733a5 From acd3a5e35f48d7afa19ce2f56a473c2b7888908d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Aug 2023 20:11:22 +1000 Subject: Remove unnecessary braces on `PatWithOr` patterns. --- compiler/rustc_expand/src/mbe/macro_rules.rs | 2 +- compiler/rustc_parse/src/parser/nonterminal.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index ce8b4621720..a5959d68fbc 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1328,7 +1328,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { _ => IsInFollow::No(TOKENS), } } - NonterminalKind::PatWithOr { .. } => { + NonterminalKind::PatWithOr => { const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"]; match tok { TokenTree::Token(token) => match token.kind { diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 7fb517ffdb8..2bf670c24ea 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -64,7 +64,7 @@ impl<'a> Parser<'a> { }, _ => false, }, - NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => { + NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => { match &token.kind { token::Ident(..) | // box, ref, mut, and other identifiers (can stricten) token::OpenDelim(Delimiter::Parenthesis) | // tuple pattern @@ -79,7 +79,7 @@ impl<'a> Parser<'a> { token::Lt | // path (UFCS constant) token::BinOp(token::Shl) => true, // path (double UFCS) // leading vert `|` or-pattern - token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr {..}), + token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr), token::Interpolated(nt) => may_be_ident(nt), _ => false, } @@ -127,10 +127,10 @@ impl<'a> Parser<'a> { .into_diagnostic(&self.sess.span_diagnostic)); } }, - NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => { + NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => { token::NtPat(self.collect_tokens_no_attrs(|this| match kind { NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None, None), - NonterminalKind::PatWithOr { .. } => this.parse_pat_allow_top_alt( + NonterminalKind::PatWithOr => this.parse_pat_allow_top_alt( None, RecoverComma::No, RecoverColon::No, -- cgit 1.4.1-3-g733a5 From f8a21a5df03f393f2c666c3033632b0024fa86ee Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Aug 2023 08:39:20 +1000 Subject: Use `Nonterminal::*` in `nonterminal.rs`. It makes the code more readable. --- compiler/rustc_parse/src/parser/nonterminal.rs | 43 ++++++++++---------------- 1 file changed, 17 insertions(+), 26 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 2bf670c24ea..fc21c0a8fd6 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -1,5 +1,5 @@ use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, NonterminalKind, Token}; +use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token}; use rustc_ast::HasTokens; use rustc_ast_pretty::pprust; use rustc_errors::IntoDiagnostic; @@ -20,10 +20,7 @@ impl<'a> Parser<'a> { pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool { /// Checks whether the non-terminal may contain a single (non-keyword) identifier. fn may_be_ident(nt: &token::Nonterminal) -> bool { - !matches!( - *nt, - token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) | token::NtLifetime(_) - ) + !matches!(*nt, NtItem(_) | NtBlock(_) | NtVis(_) | NtLifetime(_)) } match kind { @@ -46,20 +43,14 @@ impl<'a> Parser<'a> { token::OpenDelim(Delimiter::Brace) => true, token::Interpolated(nt) => !matches!( **nt, - token::NtItem(_) - | token::NtPat(_) - | token::NtTy(_) - | token::NtIdent(..) - | token::NtMeta(_) - | token::NtPath(_) - | token::NtVis(_) + NtItem(_) | NtPat(_) | NtTy(_) | NtIdent(..) | NtMeta(_) | NtPath(_) | NtVis(_) ), _ => false, }, NonterminalKind::Path | NonterminalKind::Meta => match &token.kind { token::ModSep | token::Ident(..) => true, token::Interpolated(nt) => match **nt { - token::NtPath(_) | token::NtMeta(_) => true, + NtPath(_) | NtMeta(_) => true, _ => may_be_ident(&nt), }, _ => false, @@ -87,7 +78,7 @@ impl<'a> Parser<'a> { NonterminalKind::Lifetime => match &token.kind { token::Lifetime(_) => true, token::Interpolated(nt) => { - matches!(**nt, token::NtLifetime(_)) + matches!(**nt, NtLifetime(_)) } _ => false, }, @@ -109,7 +100,7 @@ impl<'a> Parser<'a> { // Note that TT is treated differently to all the others. NonterminalKind::TT => return Ok(NtOrTt::Tt(self.parse_token_tree())), NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? { - Some(item) => token::NtItem(item), + Some(item) => NtItem(item), None => { return Err(UnexpectedNonterminal::Item(self.token.span) .into_diagnostic(&self.sess.span_diagnostic)); @@ -118,17 +109,17 @@ impl<'a> Parser<'a> { NonterminalKind::Block => { // While a block *expression* may have attributes (e.g. `#[my_attr] { ... }`), // the ':block' matcher does not support them - token::NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?) + NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?) } NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? { - Some(s) => token::NtStmt(P(s)), + Some(s) => NtStmt(P(s)), None => { return Err(UnexpectedNonterminal::Statement(self.token.span) .into_diagnostic(&self.sess.span_diagnostic)); } }, NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => { - token::NtPat(self.collect_tokens_no_attrs(|this| match kind { + NtPat(self.collect_tokens_no_attrs(|this| match kind { NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None, None), NonterminalKind::PatWithOr => this.parse_pat_allow_top_alt( None, @@ -140,15 +131,15 @@ impl<'a> Parser<'a> { })?) } - NonterminalKind::Expr => token::NtExpr(self.parse_expr_force_collect()?), + NonterminalKind::Expr => NtExpr(self.parse_expr_force_collect()?), NonterminalKind::Literal => { // The `:literal` matcher does not support attributes - token::NtLiteral( + NtLiteral( self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?, ) } - NonterminalKind::Ty => token::NtTy( + NonterminalKind::Ty => NtTy( self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?, ), @@ -157,7 +148,7 @@ impl<'a> Parser<'a> { if let Some((ident, is_raw)) = get_macro_ident(&self.token) => { self.bump(); - token::NtIdent(ident, is_raw) + NtIdent(ident, is_raw) } NonterminalKind::Ident => { return Err(UnexpectedNonterminal::Ident { @@ -165,16 +156,16 @@ impl<'a> Parser<'a> { token: self.token.clone(), }.into_diagnostic(&self.sess.span_diagnostic)); } - NonterminalKind::Path => token::NtPath( + NonterminalKind::Path => NtPath( P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?), ), - NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)), - NonterminalKind::Vis => token::NtVis( + NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(true)?)), + NonterminalKind::Vis => NtVis( P(self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?), ), NonterminalKind::Lifetime => { if self.check_lifetime() { - token::NtLifetime(self.expect_lifetime().ident) + NtLifetime(self.expect_lifetime().ident) } else { return Err(UnexpectedNonterminal::Lifetime { span: self.token.span, -- cgit 1.4.1-3-g733a5 From 9a3c907bdbab9c9e444db4c32997bf621936b891 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Aug 2023 09:25:16 +1000 Subject: Make some `match`es exhaustive in `nonterminal.rs`. For ones matching more than one or two variants, this is easier to think about. --- compiler/rustc_parse/src/parser/nonterminal.rs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index fc21c0a8fd6..3862b7640b6 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -20,7 +20,21 @@ impl<'a> Parser<'a> { pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool { /// Checks whether the non-terminal may contain a single (non-keyword) identifier. fn may_be_ident(nt: &token::Nonterminal) -> bool { - !matches!(*nt, NtItem(_) | NtBlock(_) | NtVis(_) | NtLifetime(_)) + match nt { + NtStmt(_) + | NtPat(_) + | NtExpr(_) + | NtTy(_) + | NtIdent(..) + | NtLiteral(_) // `true`, `false` + | NtMeta(_) + | NtPath(_) => true, + + NtItem(_) + | NtBlock(_) + | NtVis(_) + | NtLifetime(_) => false, + } } match kind { @@ -41,10 +55,11 @@ impl<'a> Parser<'a> { }, NonterminalKind::Block => match &token.kind { token::OpenDelim(Delimiter::Brace) => true, - token::Interpolated(nt) => !matches!( - **nt, - NtItem(_) | NtPat(_) | NtTy(_) | NtIdent(..) | NtMeta(_) | NtPath(_) | NtVis(_) - ), + token::Interpolated(nt) => match **nt { + NtBlock(_) | NtLifetime(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true, + NtItem(_) | NtPat(_) | NtTy(_) | NtIdent(..) | NtMeta(_) | NtPath(_) + | NtVis(_) => false, + }, _ => false, }, NonterminalKind::Path | NonterminalKind::Meta => match &token.kind { -- cgit 1.4.1-3-g733a5 From e46caaf84bcdfcbd7582b6ee63989f28116c3177 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Aug 2023 09:36:51 +1000 Subject: Simplify a `match`. `may_be_ident` is true for `NtPath` and `NtMeta`, so we don't need to check for them separately. --- compiler/rustc_parse/src/parser/nonterminal.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 3862b7640b6..882ecc2a7ea 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -64,10 +64,7 @@ impl<'a> Parser<'a> { }, NonterminalKind::Path | NonterminalKind::Meta => match &token.kind { token::ModSep | token::Ident(..) => true, - token::Interpolated(nt) => match **nt { - NtPath(_) | NtMeta(_) => true, - _ => may_be_ident(&nt), - }, + token::Interpolated(nt) => may_be_ident(nt), _ => false, }, NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => { -- cgit 1.4.1-3-g733a5 From dee6c9241f7402b5122266f8f59f6b731678b50a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 15 Aug 2023 09:01:22 +1000 Subject: Refactor `interpolated_or_expr_span`. It's much more complicated than it needs to be, and it doesn't modify the expression. We can do the `Result` handling outside of it, and change it to just return a span. Also fix an errant comma that makes the comment hard to read. --- compiler/rustc_parse/src/parser/expr.rs | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e409c7c6781..d17f2f0261b 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -626,8 +626,8 @@ impl<'a> Parser<'a> { fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P)> { self.bump(); - let expr = self.parse_expr_prefix(None); - let (span, expr) = self.interpolated_or_expr_span(expr)?; + let expr = self.parse_expr_prefix(None)?; + let span = self.interpolated_or_expr_span(&expr); Ok((lo.to(span), expr)) } @@ -702,20 +702,12 @@ impl<'a> Parser<'a> { self.parse_expr_unary(lo, UnOp::Not) } - /// Returns the span of expr, if it was not interpolated or the span of the interpolated token. - fn interpolated_or_expr_span( - &self, - expr: PResult<'a, P>, - ) -> PResult<'a, (Span, P)> { - expr.map(|e| { - ( - match self.prev_token.kind { - TokenKind::Interpolated(..) => self.prev_token.span, - _ => e.span, - }, - e, - ) - }) + /// Returns the span of expr if it was not interpolated, or the span of the interpolated token. + fn interpolated_or_expr_span(&self, expr: &Expr) -> Span { + match self.prev_token.kind { + TokenKind::Interpolated(..) => self.prev_token.span, + _ => expr.span, + } } fn parse_assoc_op_cast( @@ -898,8 +890,8 @@ impl<'a> Parser<'a> { self.parse_expr_prefix_range(None) } else { self.parse_expr_prefix(None) - }; - let (hi, expr) = self.interpolated_or_expr_span(expr)?; + }?; + let hi = self.interpolated_or_expr_span(&expr); let span = lo.to(hi); if let Some(lt) = lifetime { self.error_remove_borrow_lifetime(span, lt.ident.span); @@ -930,8 +922,8 @@ impl<'a> Parser<'a> { fn parse_expr_dot_or_call(&mut self, attrs: Option) -> PResult<'a, P> { let attrs = self.parse_or_use_outer_attributes(attrs)?; self.collect_tokens_for_expr(attrs, |this, attrs| { - let base = this.parse_expr_bottom(); - let (span, base) = this.interpolated_or_expr_span(base)?; + let base = this.parse_expr_bottom()?; + let span = this.interpolated_or_expr_span(&base); this.parse_expr_dot_or_call_with(base, span, attrs) }) } -- cgit 1.4.1-3-g733a5 From 9167eea553d00a790c10ebc0a821e3fa1b13d93c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 15 Aug 2023 10:35:42 +1000 Subject: Use `interpolated_or_expr_span` in one suitable place. --- compiler/rustc_parse/src/parser/expr.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index d17f2f0261b..e308e5b3420 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -193,13 +193,7 @@ impl<'a> Parser<'a> { self.expected_tokens.push(TokenType::Operator); while let Some(op) = self.check_assoc_op() { - // Adjust the span for interpolated LHS to point to the `$lhs` token - // and not to what it refers to. - let lhs_span = match self.prev_token.kind { - TokenKind::Interpolated(..) => self.prev_token.span, - _ => lhs.span, - }; - + let lhs_span = self.interpolated_or_expr_span(&lhs); let cur_op_span = self.token.span; let restrictions = if op.node.is_assign_like() { self.restrictions & Restrictions::NO_STRUCT_LITERAL -- cgit 1.4.1-3-g733a5 From 9e22351c74a9b87f452590638c6c3997f206cb72 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Aug 2023 16:43:05 +1000 Subject: Rename `NtOrTt` as `ParseNtResult`. It's more descriptive, and future-proofs it if/when additional variants get added. --- compiler/rustc_expand/src/mbe/macro_parser.rs | 6 +++--- compiler/rustc_parse/src/parser/mod.rs | 2 +- compiler/rustc_parse/src/parser/nonterminal.rs | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 05c0cd952b8..7e85beaadcb 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -81,7 +81,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::ErrorGuaranteed; use rustc_lint_defs::pluralize; -use rustc_parse::parser::{NtOrTt, Parser}; +use rustc_parse::parser::{ParseNtResult, Parser}; use rustc_span::symbol::Ident; use rustc_span::symbol::MacroRulesNormalizedIdent; use rustc_span::Span; @@ -692,8 +692,8 @@ impl TtParser { Ok(nt) => nt, }; let m = match nt { - NtOrTt::Nt(nt) => MatchedNonterminal(Lrc::new(nt)), - NtOrTt::Tt(tt) => MatchedTokenTree(tt), + ParseNtResult::Nt(nt) => MatchedNonterminal(Lrc::new(nt)), + ParseNtResult::Tt(tt) => MatchedTokenTree(tt), }; mp.push_match(next_metavar, seq_depth, m); mp.idx += 1; diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 3c3872f2706..77c59bb3881 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1491,7 +1491,7 @@ pub enum FlatToken { } #[derive(Debug)] -pub enum NtOrTt { +pub enum ParseNtResult { Nt(Nonterminal), Tt(TokenTree), } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 882ecc2a7ea..ff059a7e865 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -8,7 +8,7 @@ use rustc_span::symbol::{kw, Ident}; use crate::errors::UnexpectedNonterminal; use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; -use crate::parser::{FollowedByType, ForceCollect, NtOrTt, Parser, PathStyle}; +use crate::parser::{FollowedByType, ForceCollect, ParseNtResult, Parser, PathStyle}; impl<'a> Parser<'a> { /// Checks whether a non-terminal may begin with a particular token. @@ -103,14 +103,14 @@ impl<'a> Parser<'a> { /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`). Inlined because there is only one call /// site. #[inline] - pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt> { + pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, ParseNtResult> { // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro, // which requires having captured tokens available. Since we cannot determine // in advance whether or not a proc-macro will be (transitively) invoked, // we always capture tokens for any `Nonterminal` which needs them. let mut nt = match kind { // Note that TT is treated differently to all the others. - NonterminalKind::TT => return Ok(NtOrTt::Tt(self.parse_token_tree())), + NonterminalKind::TT => return Ok(ParseNtResult::Tt(self.parse_token_tree())), NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? { Some(item) => NtItem(item), None => { @@ -197,7 +197,7 @@ impl<'a> Parser<'a> { ); } - Ok(NtOrTt::Nt(nt)) + Ok(ParseNtResult::Nt(nt)) } } -- cgit 1.4.1-3-g733a5 From 1e87ef66f4695d650672c8db0f60128f5024df18 Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Sat, 19 Aug 2023 12:55:01 +0200 Subject: Fix a stack overflow with long else if chains --- compiler/rustc_ast/src/mut_visit.rs | 3 ++- compiler/rustc_parse/src/parser/expr.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index bae3979fbf9..48e9b180b74 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -13,6 +13,7 @@ use crate::tokenstream::*; use crate::{ast::*, StaticItem}; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; use rustc_span::source_map::Spanned; use rustc_span::symbol::Ident; @@ -1369,7 +1370,7 @@ pub fn noop_visit_expr( ExprKind::If(cond, tr, fl) => { vis.visit_expr(cond); vis.visit_block(tr); - visit_opt(fl, |fl| vis.visit_expr(fl)); + visit_opt(fl, |fl| ensure_sufficient_stack(|| vis.visit_expr(fl))); } ExprKind::While(cond, body, label) => { vis.visit_expr(cond); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e308e5b3420..9ae3ef6172c 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -22,6 +22,7 @@ use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind}; use rustc_ast_pretty::pprust; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult, StashKey, @@ -2489,7 +2490,7 @@ impl<'a> Parser<'a> { let else_span = self.prev_token.span; // `else` let attrs = self.parse_outer_attributes()?; // For recovery. let expr = if self.eat_keyword(kw::If) { - self.parse_expr_if()? + ensure_sufficient_stack(|| self.parse_expr_if())? } else if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) { self.parse_simple_block()? } else { -- cgit 1.4.1-3-g733a5