diff options
| author | Trevor Gross <t.gross35@gmail.com> | 2024-07-16 16:15:15 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-16 16:15:15 -0500 |
| commit | 9833e21c5db09ec666f044340f3fc71dd5742216 (patch) | |
| tree | 5fd26e4fe54086475cbf147eb911ee02b0da47e5 /compiler/rustc_parse/src/parser | |
| parent | 36ea06827bf32cb4d12bf479e5a56c54bd358611 (diff) | |
| parent | d0a1851ec2cf84bdb41bc4d788b3995a8463c543 (diff) | |
| download | rust-9833e21c5db09ec666f044340f3fc71dd5742216.tar.gz rust-9833e21c5db09ec666f044340f3fc71dd5742216.zip | |
Rollup merge of #126762 - compiler-errors:kw-lt, r=michaelwoerister
Deny keyword lifetimes pre-expansion https://github.com/rust-lang/rust/pull/126452#issuecomment-2179464266 > Secondly, we confirmed that we're OK with moving the validation of keywords in lifetimes to pre-expansion from post-expansion. We similarly consider this a bug fix. While the breakage of the convenience feature of the with_locals crate that relies on this is unfortunate, and we wish we had not overlooked this earlier for that reason, we're fortunate that the breakage is contained to only one crate, and we're going to accept this breakage as the extra complexity we'd need to carry in the compiler to work around this isn't deemed worth it. T-lang considers it to be a bugfix to deny `'keyword` lifetimes in the parser, rather than during AST validation that only happens post-expansion. This has one breakage: https://github.com/rust-lang/rust/pull/126452#issuecomment-2171654756 This probably should get lang FCP'd just for consistency.
Diffstat (limited to 'compiler/rustc_parse/src/parser')
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/nonterminal.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/ty.rs | 6 |
4 files changed, 25 insertions, 9 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 4bd20be4171..0ba8c66f48f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2932,10 +2932,17 @@ impl<'a> Parser<'a> { } pub(crate) fn eat_label(&mut self) -> Option<Label> { - self.token.lifetime().map(|ident| { + if let Some(ident) = self.token.lifetime() { + // Disallow `'fn`, but with a better error message than `expect_lifetime`. + if ident.without_first_quote().is_reserved() { + self.dcx().emit_err(errors::InvalidLabel { span: ident.span, name: ident.name }); + } + self.bump(); - Label { ident } - }) + Some(Label { ident }) + } else { + None + } } /// Parses a `match ... { ... }` expression (`match` token already eaten). diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 4a78b427832..41e31d76d62 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -177,8 +177,11 @@ impl<'a> Parser<'a> { .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?)) } NonterminalKind::Lifetime => { - return if self.check_lifetime() { - Ok(ParseNtResult::Lifetime(self.expect_lifetime().ident)) + // We want to keep `'keyword` parsing, just like `keyword` is still + // an ident for nonterminal purposes. + return if let Some(ident) = self.token.lifetime() { + self.bump(); + Ok(ParseNtResult::Lifetime(ident)) } else { Err(self.dcx().create_err(UnexpectedNonterminal::Lifetime { span: self.token.span, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index e4e89615d71..8e8df9f0a84 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -542,12 +542,12 @@ impl<'a> Parser<'a> { None => PatKind::Path(qself, path), } } - } else if let token::Lifetime(lt) = self.token.kind + } else if let Some(lt) = self.token.lifetime() // In pattern position, we're totally fine with using "next token isn't colon" // as a heuristic. We could probably just always try to recover if it's a lifetime, // because we never have `'a: label {}` in a pattern position anyways, but it does // keep us from suggesting something like `let 'a: Ty = ..` => `let 'a': Ty = ..` - && could_be_unclosed_char_literal(Ident::with_dummy_span(lt)) + && could_be_unclosed_char_literal(lt) && !self.look_ahead(1, |token| matches!(token.kind, token::Colon)) { // Recover a `'a` as a `'a'` literal @@ -683,12 +683,12 @@ impl<'a> Parser<'a> { /// Parse `&pat` / `&mut pat`. fn parse_pat_deref(&mut self, expected: Option<Expected>) -> PResult<'a, PatKind> { self.expect_and()?; - if let token::Lifetime(name) = self.token.kind { + if let Some(lifetime) = self.token.lifetime() { self.bump(); // `'a` self.dcx().emit_err(UnexpectedLifetimeInPattern { span: self.prev_token.span, - symbol: name, + symbol: lifetime.name, suggestion: self.prev_token.span.until(self.token.span), }); } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 94321b1dddd..68b8af7d20e 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1230,6 +1230,12 @@ impl<'a> Parser<'a> { /// Parses a single lifetime `'a` or panics. pub(super) fn expect_lifetime(&mut self) -> Lifetime { if let Some(ident) = self.token.lifetime() { + if ident.without_first_quote().is_reserved() + && ![kw::UnderscoreLifetime, kw::StaticLifetime].contains(&ident.name) + { + self.dcx().emit_err(errors::KeywordLifetime { span: ident.span }); + } + self.bump(); Lifetime { ident, id: ast::DUMMY_NODE_ID } } else { |
