about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-08-26 11:11:13 -0400
committerMichael Goulet <michael@errs.io>2024-09-06 10:32:48 -0400
commit9aaf873396186ea0c980cbea7d3449a355ccfeea (patch)
treeb2fac45d063823e935f66b6979f6ca21d82ba859
parent59d4114b2d1aaac9a6dfe770997f2e79ccfd28ab (diff)
downloadrust-9aaf873396186ea0c980cbea7d3449a355ccfeea.tar.gz
rust-9aaf873396186ea0c980cbea7d3449a355ccfeea.zip
Reserve prefix lifetimes too
-rw-r--r--compiler/rustc_lexer/src/lib.rs26
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs10
-rw-r--r--tests/ui/lexer/prefixed-lifetime.rs10
-rw-r--r--tests/ui/lexer/prefixed-lifetime.stderr14
4 files changed, 51 insertions, 9 deletions
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index 31fdd2d7cec..be3e151ea61 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -91,6 +91,12 @@ pub enum TokenKind {
     /// tokens.
     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
     /// for emoji identifier recovery, as those are not meant to be ever accepted.
     InvalidPrefix,
@@ -688,15 +694,17 @@ impl Cursor<'_> {
         self.bump();
         self.eat_while(is_id_continue);
 
-        // Check if after skipping literal contents we've met a closing
-        // single quote (which means that user attempted to create a
-        // string with single quotes).
-        if self.first() == '\'' {
-            self.bump();
-            let kind = Char { terminated: true };
-            Literal { kind, suffix_start: self.pos_within_token() }
-        } else {
-            Lifetime { starts_with_number }
+        match self.first() {
+            // Check if after skipping literal contents we've met a closing
+            // single quote (which means that user attempted to create a
+            // string with single quotes).
+            '\'' => {
+                self.bump();
+                let kind = Char { terminated: true };
+                Literal { kind, suffix_start: self.pos_within_token() }
+            }
+            '#' if !starts_with_number => UnknownPrefixLifetime,
+            _ => Lifetime { starts_with_number },
         }
     }
 
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index f30939093c2..5d2d5a6010f 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -205,6 +205,16 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
                     self.report_unknown_prefix(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::InvalidPrefix
                     // Do not recover an identifier with emoji if the codepoint is a confusable
diff --git a/tests/ui/lexer/prefixed-lifetime.rs b/tests/ui/lexer/prefixed-lifetime.rs
new file mode 100644
index 00000000000..6191b97d576
--- /dev/null
+++ b/tests/ui/lexer/prefixed-lifetime.rs
@@ -0,0 +1,10 @@
+//@ edition: 2021
+
+macro_rules! w {
+    ($($tt:tt)*) => {};
+}
+
+w!('foo#lifetime);
+//~^ ERROR prefix `'foo` is unknown
+
+fn main() {}
diff --git a/tests/ui/lexer/prefixed-lifetime.stderr b/tests/ui/lexer/prefixed-lifetime.stderr
new file mode 100644
index 00000000000..39e8b5a2a57
--- /dev/null
+++ b/tests/ui/lexer/prefixed-lifetime.stderr
@@ -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
+