summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-10-30 14:45:17 +0000
committerJosh Stone <jistone@redhat.com>2024-11-21 09:26:42 -0800
commit3c7babbb128ba0855129b543be30795ac8320f1a (patch)
tree59e81dc719b39c8ef4ea09c1170b09ed184149a6
parent4ff8ff0ecd982852e08e6af1223cee957d5b781e (diff)
downloadrust-3c7babbb128ba0855129b543be30795ac8320f1a.tar.gz
rust-3c7babbb128ba0855129b543be30795ac8320f1a.zip
Enforce that raw lifetime identifiers must be valid raw identifiers
(cherry picked from commit 9785c7cf94f5e30742f886764f2d25b6a4da66e8)
-rw-r--r--compiler/rustc_parse/messages.ftl2
-rw-r--r--compiler/rustc_parse/src/errors.rs8
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs14
-rw-r--r--tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs20
-rw-r--r--tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr32
5 files changed, 72 insertions, 4 deletions
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 1af7fb9b86a..ef259703f0c 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -77,6 +77,8 @@ parse_box_syntax_removed_suggestion = use `Box::new()` instead
 
 parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier
 
+parse_cannot_be_raw_lifetime = `{$ident}` cannot be a raw lifetime
+
 parse_catch_after_try = keyword `catch` cannot follow a `try` block
     .help = try using `match` on the result of the `try` block instead
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index fdd500e90f8..7ec4ad6dc35 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2019,6 +2019,14 @@ pub(crate) struct CannotBeRawIdent {
 }
 
 #[derive(Diagnostic)]
+#[diag(parse_cannot_be_raw_lifetime)]
+pub(crate) struct CannotBeRawLifetime {
+    #[primary_span]
+    pub span: Span,
+    pub ident: Symbol,
+}
+
+#[derive(Diagnostic)]
 #[diag(parse_keyword_lifetime)]
 pub(crate) struct KeywordLifetime {
     #[primary_span]
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index d627ef3d2cb..226de65445c 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -294,15 +294,21 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
                     let prefix_span = self.mk_sp(start, ident_start);
 
                     if prefix_span.at_least_rust_2021() {
-                        let lifetime_name_without_tick = self.str_from(ident_start);
+                        let span = self.mk_sp(start, self.pos);
+
+                        let lifetime_name_without_tick = Symbol::intern(&self.str_from(ident_start));
+                        if !lifetime_name_without_tick.can_be_raw() {
+                            self.dcx().emit_err(errors::CannotBeRawLifetime { span, ident: lifetime_name_without_tick });
+                        }
+
                         // Put the `'` back onto the lifetime name.
-                        let mut lifetime_name = String::with_capacity(lifetime_name_without_tick.len() + 1);
+                        let mut lifetime_name = String::with_capacity(lifetime_name_without_tick.as_str().len() + 1);
                         lifetime_name.push('\'');
-                        lifetime_name += lifetime_name_without_tick;
+                        lifetime_name += lifetime_name_without_tick.as_str();
                         let sym = Symbol::intern(&lifetime_name);
 
                         // Make sure we mark this as a raw identifier.
-                        self.psess.raw_identifier_spans.push(self.mk_sp(start, self.pos));
+                        self.psess.raw_identifier_spans.push(span);
 
                         token::Lifetime(sym, IdentIsRaw::Yes)
                     } else {
diff --git a/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs
new file mode 100644
index 00000000000..882fad925f3
--- /dev/null
+++ b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs
@@ -0,0 +1,20 @@
+//@ edition: 2021
+
+// Reject raw lifetimes with identifier parts that wouldn't be valid raw identifiers.
+
+macro_rules! w {
+    ($tt:tt) => {};
+}
+
+w!('r#_);
+//~^ ERROR `_` cannot be a raw lifetime
+w!('r#self);
+//~^ ERROR `self` cannot be a raw lifetime
+w!('r#super);
+//~^ ERROR `super` cannot be a raw lifetime
+w!('r#Self);
+//~^ ERROR `Self` cannot be a raw lifetime
+w!('r#crate);
+//~^ ERROR `crate` cannot be a raw lifetime
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr
new file mode 100644
index 00000000000..4cbb89b7a55
--- /dev/null
+++ b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr
@@ -0,0 +1,32 @@
+error: `_` cannot be a raw lifetime
+  --> $DIR/raw-lt-invalid-raw-id.rs:9:4
+   |
+LL | w!('r#_);
+   |    ^^^^
+
+error: `self` cannot be a raw lifetime
+  --> $DIR/raw-lt-invalid-raw-id.rs:11:4
+   |
+LL | w!('r#self);
+   |    ^^^^^^^
+
+error: `super` cannot be a raw lifetime
+  --> $DIR/raw-lt-invalid-raw-id.rs:13:4
+   |
+LL | w!('r#super);
+   |    ^^^^^^^^
+
+error: `Self` cannot be a raw lifetime
+  --> $DIR/raw-lt-invalid-raw-id.rs:15:4
+   |
+LL | w!('r#Self);
+   |    ^^^^^^^
+
+error: `crate` cannot be a raw lifetime
+  --> $DIR/raw-lt-invalid-raw-id.rs:17:4
+   |
+LL | w!('r#crate);
+   |    ^^^^^^^^
+
+error: aborting due to 5 previous errors
+