Skip to content

Commit 1c6ded5

Browse files
Reserve prefix lifetimes too
1 parent ae9f501 commit 1c6ded5

File tree

4 files changed

+51
-9
lines changed

4 files changed

+51
-9
lines changed

compiler/rustc_lexer/src/lib.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ pub enum TokenKind {
9090
/// tokens.
9191
UnknownPrefix,
9292

93+
/// An unknown prefix in a lifetime, like `'foo#`.
94+
///
95+
/// Note that like above, only the `'` and prefix are included in the token
96+
/// and not the separator.
97+
UnknownPrefixLifetime,
98+
9399
/// Similar to the above, but *always* an error on every edition. This is used
94100
/// for emoji identifier recovery, as those are not meant to be ever accepted.
95101
InvalidPrefix,
@@ -687,15 +693,17 @@ impl Cursor<'_> {
687693
self.bump();
688694
self.eat_while(is_id_continue);
689695

690-
// Check if after skipping literal contents we've met a closing
691-
// single quote (which means that user attempted to create a
692-
// string with single quotes).
693-
if self.first() == '\'' {
694-
self.bump();
695-
let kind = Char { terminated: true };
696-
Literal { kind, suffix_start: self.pos_within_token() }
697-
} else {
698-
Lifetime { starts_with_number }
696+
match self.first() {
697+
// Check if after skipping literal contents we've met a closing
698+
// single quote (which means that user attempted to create a
699+
// string with single quotes).
700+
'\'' => {
701+
self.bump();
702+
let kind = Char { terminated: true };
703+
Literal { kind, suffix_start: self.pos_within_token() }
704+
}
705+
'#' if !starts_with_number => UnknownPrefixLifetime,
706+
_ => Lifetime { starts_with_number },
699707
}
700708
}
701709

compiler/rustc_parse/src/lexer/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,16 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
205205
self.report_unknown_prefix(start);
206206
self.ident(start)
207207
}
208+
rustc_lexer::TokenKind::UnknownPrefixLifetime => {
209+
self.report_unknown_prefix(start);
210+
// Include the leading `'` in the real identifier, for macro
211+
// expansion purposes. See #12512 for the gory details of why
212+
// this is necessary.
213+
let lifetime_name = self.str_from(start);
214+
self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
215+
let ident = Symbol::intern(lifetime_name);
216+
token::Lifetime(ident, IdentIsRaw::No)
217+
}
208218
rustc_lexer::TokenKind::InvalidIdent
209219
| rustc_lexer::TokenKind::InvalidPrefix
210220
// Do not recover an identifier with emoji if the codepoint is a confusable

tests/ui/lexer/prefixed-lifetime.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//@ edition: 2021
2+
3+
macro_rules! w {
4+
($($tt:tt)*) => {};
5+
}
6+
7+
w!('foo#lifetime);
8+
//~^ ERROR prefix `'foo` is unknown
9+
10+
fn main() {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: prefix `'foo` is unknown
2+
--> $DIR/prefixed-lifetime.rs:7:4
3+
|
4+
LL | w!('foo#lifetime);
5+
| ^^^^ unknown prefix
6+
|
7+
= note: prefixed identifiers and literals are reserved since Rust 2021
8+
help: consider inserting whitespace here
9+
|
10+
LL | w!('foo #lifetime);
11+
| +
12+
13+
error: aborting due to 1 previous error
14+

0 commit comments

Comments
 (0)