From 45cb7c6731f1defe20c45fbde1f7c2d114bd4c5f Mon Sep 17 00:00:00 2001
From: xizheyin <xizheyin@smail.nju.edu.cn>
Date: Thu, 15 May 2025 18:32:01 +0800
Subject: [PATCH 1/2] Add ui test
 reverved-guarded-string-too-many-terminators-issue-140618

Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
---
 ...tring-too-many-terminators-issue-140618.rs | 38 ++++++++
 ...g-too-many-terminators-issue-140618.stderr | 88 +++++++++++++++++++
 2 files changed, 126 insertions(+)
 create mode 100644 tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.rs
 create mode 100644 tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.stderr

diff --git a/tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.rs b/tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.rs
new file mode 100644
index 0000000000000..87049d2c6b559
--- /dev/null
+++ b/tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.rs
@@ -0,0 +1,38 @@
+//@ edition:2024
+
+fn f0(){
+    r#"ok0!"#;
+}
+
+fn f1(){
+    r#"ok1!"##;
+    //~^ ERROR too many `#` when terminating raw string
+}
+
+
+fn f2(){
+    r#"ok2!"###;
+    //~^ ERROR reserved multi-hash token is forbidden
+    //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `##`
+}
+
+fn f3(){
+    #"ok3!"#;
+    //~^ ERROR invalid string literal
+}
+
+
+fn f4(){
+    #"ok4!"##;
+    //~^ ERROR invalid string literal
+    //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `#`
+}
+
+fn f5(){
+    #"ok5!"###;
+    //~^ ERROR invalid string literal
+    //~| ERROR reserved multi-hash token is forbidden
+    //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `##`
+}
+
+fn main() {}
diff --git a/tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.stderr b/tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.stderr
new file mode 100644
index 0000000000000..dd206d5996555
--- /dev/null
+++ b/tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.stderr
@@ -0,0 +1,88 @@
+error: reserved multi-hash token is forbidden
+  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:14:14
+   |
+LL |     r#"ok2!"###;
+   |              ^^
+   |
+   = note: sequences of two or more # are reserved for future use since Rust 2024
+help: consider inserting whitespace here
+   |
+LL |     r#"ok2!"## #;
+   |               +
+
+error: invalid string literal
+  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:20:5
+   |
+LL |     #"ok3!"#;
+   |     ^^^^^^^^
+   |
+   = note: unprefixed guarded string literals are reserved for future use since Rust 2024
+help: consider inserting whitespace here
+   |
+LL |     # "ok3!"#;
+   |      +
+
+error: invalid string literal
+  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:26:5
+   |
+LL |     #"ok4!"##;
+   |     ^^^^^^^^
+   |
+   = note: unprefixed guarded string literals are reserved for future use since Rust 2024
+help: consider inserting whitespace here
+   |
+LL |     # "ok4!"##;
+   |      +
+
+error: invalid string literal
+  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:32:5
+   |
+LL |     #"ok5!"###;
+   |     ^^^^^^^^
+   |
+   = note: unprefixed guarded string literals are reserved for future use since Rust 2024
+help: consider inserting whitespace here
+   |
+LL |     # "ok5!"###;
+   |      +
+
+error: reserved multi-hash token is forbidden
+  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:32:13
+   |
+LL |     #"ok5!"###;
+   |             ^^
+   |
+   = note: sequences of two or more # are reserved for future use since Rust 2024
+help: consider inserting whitespace here
+   |
+LL |     #"ok5!"## #;
+   |              +
+
+error: too many `#` when terminating raw string
+  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:8:14
+   |
+LL |     r#"ok1!"##;
+   |     ---------^ help: remove the extra `#`
+   |     |
+   |     this raw string started with 1 `#`
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `##`
+  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:14:14
+   |
+LL |     r#"ok2!"###;
+   |              ^^ expected one of `.`, `;`, `?`, `}`, or an operator
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `#`
+  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:26:13
+   |
+LL |     #"ok4!"##;
+   |             ^ expected one of `.`, `;`, `?`, `}`, or an operator
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `##`
+  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:32:13
+   |
+LL |     #"ok5!"###;
+   |             ^^ expected one of `.`, `;`, `?`, `}`, or an operator
+
+error: aborting due to 9 previous errors
+

From a09b8252e5784af40719866e9fd9798a738db9a9 Mon Sep 17 00:00:00 2001
From: xizheyin <xizheyin@smail.nju.edu.cn>
Date: Thu, 15 May 2025 18:48:33 +0800
Subject: [PATCH 2/2] Lexer: check in `advance_token` to avoid regard `##` as
 `GardedStrPrefix`

Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
---
 compiler/rustc_lexer/src/lib.rs               |  3 +-
 .../ui/rust-2024/reserved-guarded-strings.rs  |  2 +-
 .../rust-2024/reserved-guarded-strings.stderr | 27 ++++++-----
 ...tring-too-many-terminators-issue-140618.rs |  6 +--
 ...g-too-many-terminators-issue-140618.stderr | 46 +++++--------------
 5 files changed, 32 insertions(+), 52 deletions(-)

diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index b2bd5e188efdc..ffcc7648e198b 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -371,6 +371,7 @@ pub fn is_ident(string: &str) -> bool {
 impl Cursor<'_> {
     /// Parses a token from the input string.
     pub fn advance_token(&mut self) -> Token {
+        let pre_char = self.prev();
         let Some(first_char) = self.bump() else {
             return Token::new(TokenKind::Eof, 0);
         };
@@ -454,7 +455,7 @@ impl Cursor<'_> {
             }
 
             // Guarded string literal prefix: `#"` or `##`
-            '#' if matches!(self.first(), '"' | '#') => {
+            '#' if matches!(self.first(), '"' | '#') && pre_char != '#' => {
                 self.bump();
                 TokenKind::GuardedStrPrefix
             }
diff --git a/tests/ui/rust-2024/reserved-guarded-strings.rs b/tests/ui/rust-2024/reserved-guarded-strings.rs
index ae4bd670fcad9..c086e2b9e8c15 100644
--- a/tests/ui/rust-2024/reserved-guarded-strings.rs
+++ b/tests/ui/rust-2024/reserved-guarded-strings.rs
@@ -65,7 +65,7 @@ fn main() {
     demo1!(###"foo"###); //~ ERROR invalid string literal
     demo2!(#"foo"###);
     //~^ ERROR invalid string literal
-    //~| ERROR reserved multi-hash token is forbidden
+    //~| ERROR no rules expected `#`
 
     // More than 255 hashes
     demon!(####################################################################################################################################################################################################################################################################"foo");
diff --git a/tests/ui/rust-2024/reserved-guarded-strings.stderr b/tests/ui/rust-2024/reserved-guarded-strings.stderr
index fde3a719e6717..0b4710d416298 100644
--- a/tests/ui/rust-2024/reserved-guarded-strings.stderr
+++ b/tests/ui/rust-2024/reserved-guarded-strings.stderr
@@ -226,18 +226,6 @@ help: consider inserting whitespace here
 LL |     demo2!(# "foo"###);
    |             +
 
-error: reserved multi-hash token is forbidden
-  --> $DIR/reserved-guarded-strings.rs:66:19
-   |
-LL |     demo2!(#"foo"###);
-   |                   ^^
-   |
-   = note: sequences of two or more # are reserved for future use since Rust 2024
-help: consider inserting whitespace here
-   |
-LL |     demo2!(#"foo"## #);
-   |                    +
-
 error: invalid string literal
   --> $DIR/reserved-guarded-strings.rs:71:12
    |
@@ -250,5 +238,20 @@ help: consider inserting whitespace here
 LL |     demon!(# ###################################################################################################################################################################################################################################################################"foo");
    |             +
 
+error: no rules expected `#`
+  --> $DIR/reserved-guarded-strings.rs:66:20
+   |
+LL | macro_rules! demo2 {
+   | ------------------ when calling this macro
+...
+LL |     demo2!(#"foo"###);
+   |                    ^ no rules expected this token in macro call
+   |
+note: while trying to match meta-variable `$b:tt`
+  --> $DIR/reserved-guarded-strings.rs:9:13
+   |
+LL |     ( $a:tt $b:tt ) => { println!("two tokens") };
+   |             ^^^^^
+
 error: aborting due to 21 previous errors
 
diff --git a/tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.rs b/tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.rs
index 87049d2c6b559..7ef2639c03ad1 100644
--- a/tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.rs
+++ b/tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.rs
@@ -12,8 +12,7 @@ fn f1(){
 
 fn f2(){
     r#"ok2!"###;
-    //~^ ERROR reserved multi-hash token is forbidden
-    //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `##`
+    //~^ ERROR too many `#` when terminating raw string
 }
 
 fn f3(){
@@ -31,8 +30,7 @@ fn f4(){
 fn f5(){
     #"ok5!"###;
     //~^ ERROR invalid string literal
-    //~| ERROR reserved multi-hash token is forbidden
-    //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `##`
+    //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `#`
 }
 
 fn main() {}
diff --git a/tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.stderr b/tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.stderr
index dd206d5996555..7f0604391f16c 100644
--- a/tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.stderr
+++ b/tests/ui/rust-2024/reverved-guarded-string-too-many-terminators-issue-140618.stderr
@@ -1,17 +1,5 @@
-error: reserved multi-hash token is forbidden
-  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:14:14
-   |
-LL |     r#"ok2!"###;
-   |              ^^
-   |
-   = note: sequences of two or more # are reserved for future use since Rust 2024
-help: consider inserting whitespace here
-   |
-LL |     r#"ok2!"## #;
-   |               +
-
 error: invalid string literal
-  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:20:5
+  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:19:5
    |
 LL |     #"ok3!"#;
    |     ^^^^^^^^
@@ -23,7 +11,7 @@ LL |     # "ok3!"#;
    |      +
 
 error: invalid string literal
-  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:26:5
+  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:25:5
    |
 LL |     #"ok4!"##;
    |     ^^^^^^^^
@@ -35,7 +23,7 @@ LL |     # "ok4!"##;
    |      +
 
 error: invalid string literal
-  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:32:5
+  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:31:5
    |
 LL |     #"ok5!"###;
    |     ^^^^^^^^
@@ -46,18 +34,6 @@ help: consider inserting whitespace here
 LL |     # "ok5!"###;
    |      +
 
-error: reserved multi-hash token is forbidden
-  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:32:13
-   |
-LL |     #"ok5!"###;
-   |             ^^
-   |
-   = note: sequences of two or more # are reserved for future use since Rust 2024
-help: consider inserting whitespace here
-   |
-LL |     #"ok5!"## #;
-   |              +
-
 error: too many `#` when terminating raw string
   --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:8:14
    |
@@ -66,23 +42,25 @@ LL |     r#"ok1!"##;
    |     |
    |     this raw string started with 1 `#`
 
-error: expected one of `.`, `;`, `?`, `}`, or an operator, found `##`
+error: too many `#` when terminating raw string
   --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:14:14
    |
 LL |     r#"ok2!"###;
-   |              ^^ expected one of `.`, `;`, `?`, `}`, or an operator
+   |     ---------^^ help: remove the extra `#`s
+   |     |
+   |     this raw string started with 1 `#`
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `#`
-  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:26:13
+  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:25:13
    |
 LL |     #"ok4!"##;
    |             ^ expected one of `.`, `;`, `?`, `}`, or an operator
 
-error: expected one of `.`, `;`, `?`, `}`, or an operator, found `##`
-  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:32:13
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `#`
+  --> $DIR/reverved-guarded-string-too-many-terminators-issue-140618.rs:31:13
    |
 LL |     #"ok5!"###;
-   |             ^^ expected one of `.`, `;`, `?`, `}`, or an operator
+   |             ^ expected one of `.`, `;`, `?`, `}`, or an operator
 
-error: aborting due to 9 previous errors
+error: aborting due to 7 previous errors