aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_expand/src/builtin_macro.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_expand/src/builtin_macro.rs')
-rw-r--r--crates/hir_expand/src/builtin_macro.rs45
1 files changed, 25 insertions, 20 deletions
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 57bc6fbd7..6fbb9570a 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -6,7 +6,7 @@ use crate::{
6 6
7use base_db::{AnchoredPath, FileId}; 7use base_db::{AnchoredPath, FileId};
8use either::Either; 8use either::Either;
9use mbe::{parse_to_token_tree, ExpandResult}; 9use mbe::{parse_exprs_with_sep, parse_to_token_tree, ExpandResult};
10use parser::FragmentKind; 10use parser::FragmentKind;
11use syntax::ast::{self, AstToken}; 11use syntax::ast::{self, AstToken};
12 12
@@ -238,35 +238,21 @@ fn format_args_expand(
238 // ]) 238 // ])
239 // ```, 239 // ```,
240 // which is still not really correct, but close enough for now 240 // which is still not really correct, but close enough for now
241 let mut args = Vec::new(); 241 let mut args = parse_exprs_with_sep(tt, ',');
242 let mut current = Vec::new(); 242
243 for tt in tt.token_trees.iter().cloned() {
244 match tt {
245 tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => {
246 args.push(current);
247 current = Vec::new();
248 }
249 _ => {
250 current.push(tt);
251 }
252 }
253 }
254 if !current.is_empty() {
255 args.push(current);
256 }
257 if args.is_empty() { 243 if args.is_empty() {
258 return ExpandResult::only_err(mbe::ExpandError::NoMatchingRule); 244 return ExpandResult::only_err(mbe::ExpandError::NoMatchingRule);
259 } 245 }
260 for arg in &mut args { 246 for arg in &mut args {
261 // Remove `key =`. 247 // Remove `key =`.
262 if matches!(arg.get(1), Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p))) if p.char == '=' && p.spacing != tt::Spacing::Joint) 248 if matches!(arg.token_trees.get(1), Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p))) if p.char == '=' && p.spacing != tt::Spacing::Joint)
263 { 249 {
264 arg.drain(..2); 250 arg.token_trees.drain(..2);
265 } 251 }
266 } 252 }
267 let _format_string = args.remove(0); 253 let _format_string = args.remove(0);
268 let arg_tts = args.into_iter().flat_map(|arg| { 254 let arg_tts = args.into_iter().flat_map(|arg| {
269 quote! { std::fmt::ArgumentV1::new(&(##arg), std::fmt::Display::fmt), } 255 quote! { std::fmt::ArgumentV1::new(&(#arg), std::fmt::Display::fmt), }
270 }.token_trees).collect::<Vec<_>>(); 256 }.token_trees).collect::<Vec<_>>();
271 let expanded = quote! { 257 let expanded = quote! {
272 std::fmt::Arguments::new_v1(&[], &[##arg_tts]) 258 std::fmt::Arguments::new_v1(&[], &[##arg_tts])
@@ -720,6 +706,25 @@ mod tests {
720 } 706 }
721 707
722 #[test] 708 #[test]
709 fn test_format_args_expand_with_comma_exprs() {
710 let expanded = expand_builtin_macro(
711 r#"
712 #[rustc_builtin_macro]
713 macro_rules! format_args {
714 ($fmt:expr) => ({ /* compiler built-in */ });
715 ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
716 }
717 format_args!("{} {:?}", a::<A,B>(), b);
718 "#,
719 );
720
721 assert_eq!(
722 expanded,
723 r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a::<A,B>()),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(b),std::fmt::Display::fmt),])"#
724 );
725 }
726
727 #[test]
723 fn test_include_bytes_expand() { 728 fn test_include_bytes_expand() {
724 let expanded = expand_builtin_macro( 729 let expanded = expand_builtin_macro(
725 r#" 730 r#"