Deny keyword lifetimes pre-expansion
This commit is contained in:
@@ -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).
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user