about summary refs log tree commit diff
diff options
context:
space:
mode:
authorhkalbasi <hamidrezakalbasi@protonmail.com>2023-05-18 12:32:41 +0330
committerhkalbasi <hamidrezakalbasi@protonmail.com>2023-05-18 12:32:41 +0330
commit5c83e222a3e001488a313e84a3e584ac0c773d8a (patch)
treecb8f608e2a9342e7e7b13c21290eedb6758c9f7d
parenta2fba7c67ec46afc78701759719ffabf4218ad3d (diff)
downloadrust-5c83e222a3e001488a313e84a3e584ac0c773d8a.tar.gz
rust-5c83e222a3e001488a313e84a3e584ac0c773d8a.zip
fix `format_args` expansion error with raw strings
-rw-r--r--crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs33
-rw-r--r--crates/hir-expand/src/builtin_fn_macro.rs26
2 files changed, 54 insertions, 5 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 0beab57eb73..f5346898c20 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
@@ -236,6 +236,39 @@ fn main() {
 }
 
 #[test]
+fn test_format_args_expand_with_raw_strings() {
+    check(
+        r##"
+#[rustc_builtin_macro]
+macro_rules! format_args {
+    ($fmt:expr) => ({ /* compiler built-in */ });
+    ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
+}
+
+fn main() {
+    format_args!(
+        r#"{},mismatch,"{}","{}""#,
+        location_csv_pat(db, &analysis, vfs, &sm, pat_id),
+        mismatch.expected.display(db),
+        mismatch.actual.display(db)
+    );
+}
+"##,
+        expect![[r##"
+#[rustc_builtin_macro]
+macro_rules! format_args {
+    ($fmt:expr) => ({ /* compiler built-in */ });
+    ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
+}
+
+fn main() {
+    $crate::fmt::Arguments::new_v1(&[r#""#, r#",mismatch,""#, r#"",""#, r#"""#, ], &[$crate::fmt::ArgumentV1::new(&(location_csv_pat(db, &analysis, vfs, &sm, pat_id)), $crate::fmt::Display::fmt), $crate::fmt::ArgumentV1::new(&(mismatch.expected.display(db)), $crate::fmt::Display::fmt), $crate::fmt::ArgumentV1::new(&(mismatch.actual.display(db)), $crate::fmt::Display::fmt), ]);
+}
+"##]],
+    );
+}
+
+#[test]
 fn test_format_args_expand_eager() {
     check(
         r#"
diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs
index 3f9ea96545c..e9e1c6c3b33 100644
--- a/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/crates/hir-expand/src/builtin_fn_macro.rs
@@ -287,16 +287,27 @@ fn format_args_expand_general(
         match token_tree {
             tt::TokenTree::Leaf(l) => match l {
                 tt::Leaf::Literal(l) => {
-                    let text = l.text.strip_prefix('"')?.strip_suffix('"')?;
-                    let span = l.span;
-                    Some((text, span))
+                    if let Some(mut text) = l.text.strip_prefix('r') {
+                        let mut raw_sharps = String::new();
+                        while let Some(t) = text.strip_prefix('#') {
+                            text = t;
+                            raw_sharps.push('#');
+                        }
+                        text =
+                            text.strip_suffix(&raw_sharps)?.strip_prefix('"')?.strip_suffix('"')?;
+                        Some((text, l.span, Some(raw_sharps)))
+                    } else {
+                        let text = l.text.strip_prefix('"')?.strip_suffix('"')?;
+                        let span = l.span;
+                        Some((text, span, None))
+                    }
                 }
                 _ => None,
             },
             tt::TokenTree::Subtree(_) => None,
         }
     })();
-    let Some((format_string, _format_string_span)) = format_string else {
+    let Some((format_string, _format_string_span, raw_sharps)) = format_string else {
         return expand_error;
     };
     let mut format_iter = format_string.chars().peekable();
@@ -379,7 +390,12 @@ fn format_args_expand_general(
         parts.push(last_part);
     }
     let part_tts = parts.into_iter().map(|x| {
-        let l = tt::Literal { span: tt::TokenId::unspecified(), text: format!("\"{}\"", x).into() };
+        let text = if let Some(raw) = &raw_sharps {
+            format!("r{raw}\"{}\"{raw}", x).into()
+        } else {
+            format!("\"{}\"", x).into()
+        };
+        let l = tt::Literal { span: tt::TokenId::unspecified(), text };
         quote!(#l ,)
     });
     let arg_tts = arg_tts.into_iter().flat_map(|arg| arg.token_trees);