Reserve prefix lifetimes too
This commit is contained in:
parent
59d4114b2d
commit
9aaf873396
@ -91,6 +91,12 @@ pub enum TokenKind {
|
|||||||
/// tokens.
|
/// tokens.
|
||||||
UnknownPrefix,
|
UnknownPrefix,
|
||||||
|
|
||||||
|
/// An unknown prefix in a lifetime, like `'foo#`.
|
||||||
|
///
|
||||||
|
/// Note that like above, only the `'` and prefix are included in the token
|
||||||
|
/// and not the separator.
|
||||||
|
UnknownPrefixLifetime,
|
||||||
|
|
||||||
/// Similar to the above, but *always* an error on every edition. This is used
|
/// Similar to the above, but *always* an error on every edition. This is used
|
||||||
/// for emoji identifier recovery, as those are not meant to be ever accepted.
|
/// for emoji identifier recovery, as those are not meant to be ever accepted.
|
||||||
InvalidPrefix,
|
InvalidPrefix,
|
||||||
@ -688,15 +694,17 @@ fn lifetime_or_char(&mut self) -> TokenKind {
|
|||||||
self.bump();
|
self.bump();
|
||||||
self.eat_while(is_id_continue);
|
self.eat_while(is_id_continue);
|
||||||
|
|
||||||
|
match self.first() {
|
||||||
// Check if after skipping literal contents we've met a closing
|
// Check if after skipping literal contents we've met a closing
|
||||||
// single quote (which means that user attempted to create a
|
// single quote (which means that user attempted to create a
|
||||||
// string with single quotes).
|
// string with single quotes).
|
||||||
if self.first() == '\'' {
|
'\'' => {
|
||||||
self.bump();
|
self.bump();
|
||||||
let kind = Char { terminated: true };
|
let kind = Char { terminated: true };
|
||||||
Literal { kind, suffix_start: self.pos_within_token() }
|
Literal { kind, suffix_start: self.pos_within_token() }
|
||||||
} else {
|
}
|
||||||
Lifetime { starts_with_number }
|
'#' if !starts_with_number => UnknownPrefixLifetime,
|
||||||
|
_ => Lifetime { starts_with_number },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +205,16 @@ fn next_token(&mut self) -> (Token, bool) {
|
|||||||
self.report_unknown_prefix(start);
|
self.report_unknown_prefix(start);
|
||||||
self.ident(start)
|
self.ident(start)
|
||||||
}
|
}
|
||||||
|
rustc_lexer::TokenKind::UnknownPrefixLifetime => {
|
||||||
|
self.report_unknown_prefix(start);
|
||||||
|
// Include the leading `'` in the real identifier, for macro
|
||||||
|
// expansion purposes. See #12512 for the gory details of why
|
||||||
|
// this is necessary.
|
||||||
|
let lifetime_name = self.str_from(start);
|
||||||
|
self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
|
||||||
|
let ident = Symbol::intern(lifetime_name);
|
||||||
|
token::Lifetime(ident, IdentIsRaw::No)
|
||||||
|
}
|
||||||
rustc_lexer::TokenKind::InvalidIdent
|
rustc_lexer::TokenKind::InvalidIdent
|
||||||
| rustc_lexer::TokenKind::InvalidPrefix
|
| rustc_lexer::TokenKind::InvalidPrefix
|
||||||
// Do not recover an identifier with emoji if the codepoint is a confusable
|
// Do not recover an identifier with emoji if the codepoint is a confusable
|
||||||
|
10
tests/ui/lexer/prefixed-lifetime.rs
Normal file
10
tests/ui/lexer/prefixed-lifetime.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
//@ edition: 2021
|
||||||
|
|
||||||
|
macro_rules! w {
|
||||||
|
($($tt:tt)*) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
w!('foo#lifetime);
|
||||||
|
//~^ ERROR prefix `'foo` is unknown
|
||||||
|
|
||||||
|
fn main() {}
|
14
tests/ui/lexer/prefixed-lifetime.stderr
Normal file
14
tests/ui/lexer/prefixed-lifetime.stderr
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
error: prefix `'foo` is unknown
|
||||||
|
--> $DIR/prefixed-lifetime.rs:7:4
|
||||||
|
|
|
||||||
|
LL | w!('foo#lifetime);
|
||||||
|
| ^^^^ unknown prefix
|
||||||
|
|
|
||||||
|
= note: prefixed identifiers and literals are reserved since Rust 2021
|
||||||
|
help: consider inserting whitespace here
|
||||||
|
|
|
||||||
|
LL | w!('foo #lifetime);
|
||||||
|
| +
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
Loading…
Reference in New Issue
Block a user