Skip to content

Commit 9aaf873

Browse files
Reserve prefix lifetimes too
1 parent 59d4114 commit 9aaf873

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
@@ -91,6 +91,12 @@ pub enum TokenKind {
9191
/// tokens.
9292
UnknownPrefix,
9393

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

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

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)