about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Barsky <me@davidbarsky.com>2025-04-28 21:12:21 +0000
committerGitHub <noreply@github.com>2025-04-28 21:12:21 +0000
commit0b02aed854596fb7a4af656726977c9ef14dfabd (patch)
treeb0d761ee2f4fd0e6c37e02b6fb1af0e736ebe7c4
parentb602274c3fa28d9a1b1c6ac3af618f40bcf4c899 (diff)
parent8118676a08fa00ce5a8ffac6427c95c4df9a2e9b (diff)
downloadrust-0b02aed854596fb7a4af656726977c9ef14dfabd.tar.gz
rust-0b02aed854596fb7a4af656726977c9ef14dfabd.zip
Merge pull request #19699 from ChayimFriedman2/escape-label
fix: Escape raw names in labels properly
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/name.rs23
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs16
3 files changed, 36 insertions, 7 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
index d43ef38f291..217d991d110 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
@@ -191,7 +191,7 @@ impl Name {
     // FIXME: Remove this in favor of `display`, see fixme on `as_str`
     #[doc(hidden)]
     pub fn display_no_db(&self, edition: Edition) -> impl fmt::Display + '_ {
-        Display { name: self, needs_escaping: is_raw_identifier(self.symbol.as_str(), edition) }
+        Display { name: self, edition }
     }
 
     pub fn symbol(&self) -> &Symbol {
@@ -201,15 +201,28 @@ impl Name {
 
 struct Display<'a> {
     name: &'a Name,
-    needs_escaping: bool,
+    edition: Edition,
 }
 
 impl fmt::Display for Display<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if self.needs_escaping {
-            write!(f, "r#")?;
+        let mut symbol = self.name.symbol.as_str();
+
+        if symbol == "'static" {
+            // FIXME: '`static` can also be a label, and there it does need escaping.
+            // But knowing where it is will require adding a parameter to `display()`,
+            // and that is an infectious change.
+            return f.write_str(symbol);
+        }
+
+        if let Some(s) = symbol.strip_prefix('\'') {
+            f.write_str("'")?;
+            symbol = s;
+        }
+        if is_raw_identifier(symbol, self.edition) {
+            f.write_str("r#")?;
         }
-        fmt::Display::fmt(self.name.symbol.as_str(), f)
+        f.write_str(symbol)
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs
index b02f079b721..8902cd09cec 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs
@@ -116,13 +116,13 @@ fn foo<'lifetime>(foo: &'a$0) {}
         check(
             r#"
 struct Foo;
-impl<'impl> Foo {
+impl<'r#impl> Foo {
     fn foo<'func>(&'a$0 self) {}
 }
 "#,
             expect![[r#"
                 lt 'func
-                lt 'impl
+                lt 'r#impl
                 lt 'static
             "#]],
         );
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
index b30ac43bf8f..27d6bc7b14f 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
@@ -2110,3 +2110,19 @@ fn foo() {
         "#]],
     );
 }
+
+#[test]
+fn escaped_label() {
+    check(
+        r#"
+fn main() {
+    'r#break: {
+        break '$0;
+    }
+}
+    "#,
+        expect![[r#"
+            lb 'r#break
+        "#]],
+    );
+}