1
Fork 0

Add initial support for raw lifetimes

This commit is contained in:
Michael Goulet 2024-09-05 05:43:55 -04:00
parent 3b3e43a386
commit 97910580aa
18 changed files with 116 additions and 40 deletions

View file

@ -2050,7 +2050,7 @@ impl<'a> Parser<'a> {
};
// On an error path, eagerly consider a lifetime to be an unclosed character lit, if that
// makes sense.
if let Some(ident) = self.token.lifetime()
if let Some((ident, IdentIsRaw::No)) = self.token.lifetime()
&& could_be_unclosed_char_literal(ident)
{
let lt = self.expect_lifetime();
@ -2925,9 +2925,9 @@ impl<'a> Parser<'a> {
}
pub(crate) fn eat_label(&mut self) -> Option<Label> {
if let Some(ident) = self.token.lifetime() {
if let Some((ident, is_raw)) = self.token.lifetime() {
// Disallow `'fn`, but with a better error message than `expect_lifetime`.
if ident.without_first_quote().is_reserved() {
if matches!(is_raw, IdentIsRaw::No) && ident.without_first_quote().is_reserved() {
self.dcx().emit_err(errors::InvalidLabel { span: ident.span, name: ident.name });
}

View file

@ -1666,7 +1666,7 @@ enum FlatToken {
pub enum ParseNtResult {
Tt(TokenTree),
Ident(Ident, IdentIsRaw),
Lifetime(Ident),
Lifetime(Ident, IdentIsRaw),
/// This case will eventually be removed, along with `Token::Interpolate`.
Nt(Lrc<Nonterminal>),

View file

@ -88,7 +88,7 @@ impl<'a> Parser<'a> {
},
NonterminalKind::Pat(pat_kind) => token.can_begin_pattern(pat_kind),
NonterminalKind::Lifetime => match &token.kind {
token::Lifetime(_) | token::NtLifetime(..) => true,
token::Lifetime(..) | token::NtLifetime(..) => true,
_ => false,
},
NonterminalKind::TT | NonterminalKind::Item | NonterminalKind::Stmt => {
@ -171,9 +171,9 @@ impl<'a> Parser<'a> {
NonterminalKind::Lifetime => {
// We want to keep `'keyword` parsing, just like `keyword` is still
// an ident for nonterminal purposes.
return if let Some(ident) = self.token.lifetime() {
return if let Some((ident, is_raw)) = self.token.lifetime() {
self.bump();
Ok(ParseNtResult::Lifetime(ident))
Ok(ParseNtResult::Lifetime(ident, is_raw))
} else {
Err(self.dcx().create_err(UnexpectedNonterminal::Lifetime {
span: self.token.span,

View file

@ -1,6 +1,6 @@
use rustc_ast::mut_visit::{walk_pat, MutVisitor};
use rustc_ast::ptr::P;
use rustc_ast::token::{self, BinOpToken, Delimiter, Token};
use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token};
use rustc_ast::{
self as ast, AttrVec, BindingMode, ByRef, Expr, ExprKind, MacCall, Mutability, Pat, PatField,
PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
@ -548,7 +548,7 @@ impl<'a> Parser<'a> {
None => PatKind::Path(qself, path),
}
}
} else if let Some(lt) = self.token.lifetime()
} else if let Some((lt, IdentIsRaw::No)) = 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
@ -689,7 +689,7 @@ 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 Some(lifetime) = self.token.lifetime() {
if let Some((lifetime, _)) = self.token.lifetime() {
self.bump(); // `'a`
self.dcx().emit_err(UnexpectedLifetimeInPattern {

View file

@ -1,5 +1,5 @@
use rustc_ast::ptr::P;
use rustc_ast::token::{self, BinOpToken, Delimiter, Token, TokenKind};
use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token, TokenKind};
use rustc_ast::util::case::Case;
use rustc_ast::{
self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound,
@ -1285,8 +1285,9 @@ 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()
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)
{
self.dcx().emit_err(errors::KeywordLifetime { span: ident.span });