about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-12-01 14:30:08 +0100
committerGitHub <noreply@github.com>2024-12-01 14:30:08 +0100
commit337c48cec54f3e88d503f759796dfa925d94072b (patch)
treece7a3a0d90e874de82383740ff85e974c7b9c60c
parentb57415839486893b1605d92d40918a90ffa653b1 (diff)
parentd878fd8877669005ee05de0c5c60021109580934 (diff)
downloadrust-337c48cec54f3e88d503f759796dfa925d94072b.tar.gz
rust-337c48cec54f3e88d503f759796dfa925d94072b.zip
Rollup merge of #133482 - compiler-errors:raw-lt-tick, r=estebank
Only error raw lifetime followed by `\'` in edition 2021+

Fixes #133479
cc #132341

I think this fixes a purely theoretical regression since it only affects edition 2015 (who is using that?) and only in the very rare case of a raw lifetime followed immediately by a lifetime like `'r#a'r`.
-rw-r--r--compiler/rustc_lexer/src/lib.rs12
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs23
-rw-r--r--tests/ui/lifetimes/raw/immediately-followed-by-lt.e2021.stderr (renamed from tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr)2
-rw-r--r--tests/ui/lifetimes/raw/immediately-followed-by-lt.rs8
4 files changed, 29 insertions, 16 deletions
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index b584e7afd98..6caeec1b5cc 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -707,17 +707,7 @@ impl Cursor<'_> {
             self.bump();
             self.bump();
             self.eat_while(is_id_continue);
-            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 };
-                    return Literal { kind, suffix_start: self.pos_within_token() };
-                }
-                _ => return RawLifetime,
-            }
+            return RawLifetime;
         }
 
         // Either a lifetime or a character literal with
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 8a42cf388f9..d97f05dc7eb 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -300,6 +300,26 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
                     let prefix_span = self.mk_sp(start, ident_start);
 
                     if prefix_span.at_least_rust_2021() {
+                        // If the raw lifetime is followed by \' then treat it a normal
+                        // lifetime followed by a \', which is to interpret it as a character
+                        // literal. In this case, it's always an invalid character literal
+                        // since the literal must necessarily have >3 characters (r#...) inside
+                        // of it, which is invalid.
+                        if self.cursor.as_str().starts_with('\'') {
+                            let lit_span = self.mk_sp(start, self.pos + BytePos(1));
+                            let contents = self.str_from_to(start + BytePos(1), self.pos);
+                            emit_unescape_error(
+                                self.dcx(),
+                                contents,
+                                lit_span,
+                                lit_span,
+                                Mode::Char,
+                                0..contents.len(),
+                                EscapeError::MoreThanOneChar,
+                            )
+                            .expect("expected error");
+                        }
+
                         let span = self.mk_sp(start, self.pos);
 
                         let lifetime_name_without_tick =
@@ -371,8 +391,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
                 rustc_lexer::TokenKind::Caret => token::BinOp(token::Caret),
                 rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent),
 
-                rustc_lexer::TokenKind::Unknown
-                | rustc_lexer::TokenKind::InvalidIdent => {
+                rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => {
                     // Don't emit diagnostics for sequences of the same invalid token
                     if swallow_next_invalid > 0 {
                         swallow_next_invalid -= 1;
diff --git a/tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr b/tests/ui/lifetimes/raw/immediately-followed-by-lt.e2021.stderr
index 1caeec84b22..e600cc37fc4 100644
--- a/tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr
+++ b/tests/ui/lifetimes/raw/immediately-followed-by-lt.e2021.stderr
@@ -1,5 +1,5 @@
 error: character literal may only contain one codepoint
-  --> $DIR/immediately-followed-by-lt.rs:11:4
+  --> $DIR/immediately-followed-by-lt.rs:15:4
    |
 LL | w!('r#long'id);
    |    ^^^^^^^^
diff --git a/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs b/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs
index fe2b6de7bb3..eb161f9c855 100644
--- a/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs
+++ b/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs
@@ -1,4 +1,8 @@
-//@ edition: 2021
+//@ revisions: e2015 e2021
+
+//@[e2021] edition: 2021
+//@[e2015] edition: 2015
+//@[e2015] check-pass
 
 // Make sure we reject the case where a raw lifetime is immediately followed by another
 // lifetime. This reserves a modest amount of space for changing lexing to, for example,
@@ -9,6 +13,6 @@ macro_rules! w {
 }
 
 w!('r#long'id);
-//~^ ERROR character literal may only contain one codepoint
+//[e2021]~^ ERROR character literal may only contain one codepoint
 
 fn main() {}