Skip to content

Commit b5efcfc

Browse files
committed
fix format_args expansion error with raw strings
1 parent a2fba7c commit b5efcfc

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,39 @@ fn main() {
235235
);
236236
}
237237

238+
#[test]
239+
fn test_format_args_expand_with_raw_strings() {
240+
check(
241+
r##"
242+
#[rustc_builtin_macro]
243+
macro_rules! format_args {
244+
($fmt:expr) => ({ /* compiler built-in */ });
245+
($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
246+
}
247+
248+
fn main() {
249+
format_args!(
250+
r#"{},mismatch,"{}","{}""#,
251+
location_csv_pat(db, &analysis, vfs, &sm, pat_id),
252+
mismatch.expected.display(db),
253+
mismatch.actual.display(db)
254+
);
255+
}
256+
"##,
257+
expect![[r##"
258+
#[rustc_builtin_macro]
259+
macro_rules! format_args {
260+
($fmt:expr) => ({ /* compiler built-in */ });
261+
($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
262+
}
263+
264+
fn main() {
265+
$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), ]);
266+
}
267+
"##]],
268+
);
269+
}
270+
238271
#[test]
239272
fn test_format_args_expand_eager() {
240273
check(

crates/hir-expand/src/builtin_fn_macro.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -287,16 +287,26 @@ fn format_args_expand_general(
287287
match token_tree {
288288
tt::TokenTree::Leaf(l) => match l {
289289
tt::Leaf::Literal(l) => {
290-
let text = l.text.strip_prefix('"')?.strip_suffix('"')?;
291-
let span = l.span;
292-
Some((text, span))
290+
if let Some(mut text) = l.text.strip_prefix('r') {
291+
let mut raw_sharps = String::new();
292+
while let Some(t) = text.strip_prefix('#') {
293+
text = t;
294+
raw_sharps.push('#');
295+
}
296+
text = text.strip_suffix(&raw_sharps)?.strip_suffix('"')?;
297+
Some((text, l.span, Some(raw_sharps)))
298+
} else {
299+
let text = l.text.strip_prefix('"')?.strip_suffix('"')?;
300+
let span = l.span;
301+
Some((text, span, None))
302+
}
293303
}
294304
_ => None,
295305
},
296306
tt::TokenTree::Subtree(_) => None,
297307
}
298308
})();
299-
let Some((format_string, _format_string_span)) = format_string else {
309+
let Some((format_string, _format_string_span, raw_sharps)) = format_string else {
300310
return expand_error;
301311
};
302312
let mut format_iter = format_string.chars().peekable();
@@ -379,7 +389,12 @@ fn format_args_expand_general(
379389
parts.push(last_part);
380390
}
381391
let part_tts = parts.into_iter().map(|x| {
382-
let l = tt::Literal { span: tt::TokenId::unspecified(), text: format!("\"{}\"", x).into() };
392+
let text = if let Some(raw) = &raw_sharps {
393+
format!("r{raw}\"{}\"{raw}", x).into()
394+
} else {
395+
format!("\"{}\"", x).into()
396+
};
397+
let l = tt::Literal { span: tt::TokenId::unspecified(), text };
383398
quote!(#l ,)
384399
});
385400
let arg_tts = arg_tts.into_iter().flat_map(|arg| arg.token_trees);

0 commit comments

Comments
 (0)