about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-04-04 20:41:30 +0200
committerGitHub <noreply@github.com>2022-04-04 20:41:30 +0200
commit2d1496a8f62afb3ff3b7e4233c2eb65593d89780 (patch)
treebf97266ddece38bd6f7f9f1778664c1e9407e6bd
parent98168925f6570a8d0292abd493cf20bde89c7663 (diff)
parentf383134acc48c97bbf2389aa62d51b9a51535482 (diff)
downloadrust-2d1496a8f62afb3ff3b7e4233c2eb65593d89780.tar.gz
rust-2d1496a8f62afb3ff3b7e4233c2eb65593d89780.zip
Rollup merge of #95343 - dtolnay:literals, r=petrochenkov
Reduce unnecessary escaping in proc_macro::Literal::character/string

I noticed that https://doc.rust-lang.org/proc_macro/struct.Literal.html#method.character is producing unreadable literals that make macro-expanded code unnecessarily hard to read. Since the proc macro server was using `escape_unicode()`, every char is escaped using `\u{…}` regardless of whether there is any need to do so. For example `Literal::character('=')` would previously produce `'\u{3d}'` which unnecessarily obscures the meaning when reading the macro-expanded code.

I've changed Literal::string also in this PR because `str`'s `Debug` impl is also smarter than just calling `escape_debug` on every char. For example `Literal::string("ferris's")` would previously produce `"ferris\'s"` but will now produce `"ferris's"`.
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs16
-rw-r--r--src/test/ui/proc-macro/auxiliary/api/parse.rs11
-rw-r--r--src/test/ui/proc-macro/quote-debug.stdout4
3 files changed, 21 insertions, 10 deletions
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index bfdf99762f5..20351070f71 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -658,16 +658,16 @@ impl server::Literal for Rustc<'_, '_> {
         self.lit(token::Float, Symbol::intern(n), Some(sym::f64))
     }
     fn string(&mut self, string: &str) -> Self::Literal {
-        let mut escaped = String::new();
-        for ch in string.chars() {
-            escaped.extend(ch.escape_debug());
-        }
-        self.lit(token::Str, Symbol::intern(&escaped), None)
+        let quoted = format!("{:?}", string);
+        assert!(quoted.starts_with('"') && quoted.ends_with('"'));
+        let symbol = &quoted[1..quoted.len() - 1];
+        self.lit(token::Str, Symbol::intern(symbol), None)
     }
     fn character(&mut self, ch: char) -> Self::Literal {
-        let mut escaped = String::new();
-        escaped.extend(ch.escape_unicode());
-        self.lit(token::Char, Symbol::intern(&escaped), None)
+        let quoted = format!("{:?}", ch);
+        assert!(quoted.starts_with('\'') && quoted.ends_with('\''));
+        let symbol = &quoted[1..quoted.len() - 1];
+        self.lit(token::Char, Symbol::intern(symbol), None)
     }
     fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal {
         let string = bytes
diff --git a/src/test/ui/proc-macro/auxiliary/api/parse.rs b/src/test/ui/proc-macro/auxiliary/api/parse.rs
index 6186b941ef6..27391f83111 100644
--- a/src/test/ui/proc-macro/auxiliary/api/parse.rs
+++ b/src/test/ui/proc-macro/auxiliary/api/parse.rs
@@ -18,6 +18,17 @@ fn test_display_literal() {
         Literal::f64_unsuffixed(1e100).to_string(),
         "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0",
     );
+
+    assert_eq!(
+        Literal::string("a \t ❤ ' \" \u{1}").to_string(),
+        "\"a \\t ❤ ' \\\" \\u{1}\"",
+    );
+    assert_eq!(Literal::character('a').to_string(), "'a'");
+    assert_eq!(Literal::character('\t').to_string(), "'\\t'");
+    assert_eq!(Literal::character('❤').to_string(), "'❤'");
+    assert_eq!(Literal::character('\'').to_string(), "'\\''");
+    assert_eq!(Literal::character('"').to_string(), "'\"'");
+    assert_eq!(Literal::character('\u{1}').to_string(), "'\\u{1}'");
 }
 
 fn test_parse_literal() {
diff --git a/src/test/ui/proc-macro/quote-debug.stdout b/src/test/ui/proc-macro/quote-debug.stdout
index ec54851fcf9..d2cc5c6e2a3 100644
--- a/src/test/ui/proc-macro/quote-debug.stdout
+++ b/src/test/ui/proc-macro/quote-debug.stdout
@@ -22,7 +22,7 @@ fn main() {
                                     crate::Span::recover_proc_macro_span(0)))),
                         crate::TokenStream::from(crate::TokenTree::Ident(crate::Ident::new("hello",
                                     crate::Span::recover_proc_macro_span(1)))),
-                        crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new('\u{3d}',
+                        crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new('=',
                                     crate::Spacing::Alone))),
                         crate::TokenStream::from(crate::TokenTree::Literal({
                                     let mut iter =
@@ -35,7 +35,7 @@ fn main() {
                                            ::core::panicking::panic("internal error: entered unreachable code")
                                        }
                                 })),
-                        crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new('\u{3b}',
+                        crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new(';',
                                     crate::Spacing::Alone)))].iter().cloned().collect::<crate::TokenStream>()
 }
 const _: () =