From 859d467276bf45e621858069192d7a68c42d2a32 Mon Sep 17 00:00:00 2001
From: Ryo Yoshida <low.ryoshida@gmail.com>
Date: Fri, 5 Aug 2022 02:51:38 +0900
Subject: [PATCH 1/2] fix: make `concat!` work with char

---
 .../src/macro_expansion_tests/builtin_fn_macro.rs  |  4 ++--
 crates/hir-expand/src/builtin_fn_macro.rs          | 14 ++++++++++++--
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index 92dffa7f372..32006c4b43e 100644
--- a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -295,13 +295,13 @@ fn test_concat_expand() {
 #[rustc_builtin_macro]
 macro_rules! concat {}
 
-fn main() { concat!("foo", "r", 0, r#"bar"#, "\n", false); }
+fn main() { concat!("foo", "r", 0, r#"bar"#, "\n", false, '\n'); }
 "##,
         expect![[r##"
 #[rustc_builtin_macro]
 macro_rules! concat {}
 
-fn main() { "foor0bar\nfalse"; }
+fn main() { "foor0bar\nfalse\n"; }
 "##]],
     );
 }
diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs
index 76da7c9f1ee..c21b35cdc09 100644
--- a/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/crates/hir-expand/src/builtin_fn_macro.rs
@@ -357,6 +357,12 @@ fn unquote_str(lit: &tt::Literal) -> Option<String> {
     token.value().map(|it| it.into_owned())
 }
 
+fn unquote_char(lit: &tt::Literal) -> Option<char> {
+    let lit = ast::make::tokens::literal(&lit.to_string());
+    let token = ast::Char::cast(lit)?;
+    token.value()
+}
+
 fn unquote_byte_string(lit: &tt::Literal) -> Option<Vec<u8>> {
     let lit = ast::make::tokens::literal(&lit.to_string());
     let token = ast::ByteString::cast(lit)?;
@@ -408,8 +414,12 @@ fn concat_expand(
                 // concat works with string and char literals, so remove any quotes.
                 // It also works with integer, float and boolean literals, so just use the rest
                 // as-is.
-                let component = unquote_str(it).unwrap_or_else(|| it.text.to_string());
-                text.push_str(&component);
+                if let Some(c) = unquote_char(it) {
+                    text.push(c);
+                } else {
+                    let component = unquote_str(it).unwrap_or_else(|| it.text.to_string());
+                    text.push_str(&component);
+                }
             }
             // handle boolean literals
             tt::TokenTree::Leaf(tt::Leaf::Ident(id))

From 4d5873e92f50f3f08f98f04ade4768f9d9ab380f Mon Sep 17 00:00:00 2001
From: Ryo Yoshida <low.ryoshida@gmail.com>
Date: Fri, 5 Aug 2022 22:01:09 +0900
Subject: [PATCH 2/2] minor: align with rustc on escaping characters in macro
 expansion

---
 crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs | 4 ++--
 crates/hir-expand/src/quote.rs                               | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index 32006c4b43e..4f626105a53 100644
--- a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -295,13 +295,13 @@ fn test_concat_expand() {
 #[rustc_builtin_macro]
 macro_rules! concat {}
 
-fn main() { concat!("foo", "r", 0, r#"bar"#, "\n", false, '\n'); }
+fn main() { concat!("foo", "r", 0, r#"bar"#, "\n", false, '"', '\0'); }
 "##,
         expect![[r##"
 #[rustc_builtin_macro]
 macro_rules! concat {}
 
-fn main() { "foor0bar\nfalse\n"; }
+fn main() { "foor0bar\nfalse\"\u{0}"; }
 "##]],
     );
 }
diff --git a/crates/hir-expand/src/quote.rs b/crates/hir-expand/src/quote.rs
index 82f410ecda9..e839e97bf02 100644
--- a/crates/hir-expand/src/quote.rs
+++ b/crates/hir-expand/src/quote.rs
@@ -196,8 +196,8 @@ impl_to_to_tokentrees! {
     tt::Literal => self { self };
     tt::Ident => self { self };
     tt::Punct => self { self };
-    &str => self { tt::Literal{text: format!("\"{}\"", self.escape_debug()).into(), id: tt::TokenId::unspecified()}};
-    String => self { tt::Literal{text: format!("\"{}\"", self.escape_debug()).into(), id: tt::TokenId::unspecified()}}
+    &str => self { tt::Literal{text: format!("\"{}\"", self.escape_default()).into(), id: tt::TokenId::unspecified()}};
+    String => self { tt::Literal{text: format!("\"{}\"", self.escape_default()).into(), id: tt::TokenId::unspecified()}}
 }
 
 #[cfg(test)]