diff options
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 { |
