From c5ffb0dc815358712a42f9358cc3538f9a7b3014 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 6 Dec 2019 10:57:20 +0100 Subject: Add stub implementation of format_args{_nl} macros Just enough to fix the huge amount of type mismatches they cause. --- crates/ra_hir_expand/src/builtin_macro.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'crates/ra_hir_expand/src/builtin_macro.rs') diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index 35f99b2bc..e0709704a 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -49,7 +49,11 @@ register_builtin! { (COMPILE_ERROR_MACRO, CompileError) => compile_error_expand, (FILE_MACRO, File) => file_expand, (LINE_MACRO, Line) => line_expand, - (STRINGIFY_MACRO, Stringify) => stringify_expand + (STRINGIFY_MACRO, Stringify) => stringify_expand, + (FORMAT_ARGS_MACRO, FormatArgs) => format_args_expand, + // format_args_nl only differs in that it adds a newline in the end, + // so we use the same stub expansion for now + (FORMAT_ARGS_NL_MACRO, FormatArgsNl) => format_args_expand } fn to_line_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize { @@ -200,6 +204,19 @@ fn compile_error_expand( Err(mbe::ExpandError::BindingError("Must be a string".into())) } +fn format_args_expand( + _db: &dyn AstDatabase, + _id: MacroCallId, + _tt: &tt::Subtree, +) -> Result { + // FIXME this is just a stub to make format macros type-check without mismatches + // We should make this at least insert the arguments, so that go to def etc. work within format macros + let expanded = quote! { + std::fmt::Arguments::new_v1(&[], &[]) + }; + Ok(expanded) +} + #[cfg(test)] mod tests { use super::*; -- cgit v1.2.3 From eae425b10fd7803ae67d2d39e9aca902daa353ba Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 6 Dec 2019 19:30:01 +0100 Subject: Implement format_args more properly --- crates/ra_hir_expand/src/builtin_macro.rs | 47 ++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 4 deletions(-) (limited to 'crates/ra_hir_expand/src/builtin_macro.rs') diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index e0709704a..99303188b 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -207,12 +207,34 @@ fn compile_error_expand( fn format_args_expand( _db: &dyn AstDatabase, _id: MacroCallId, - _tt: &tt::Subtree, + tt: &tt::Subtree, ) -> Result { - // FIXME this is just a stub to make format macros type-check without mismatches - // We should make this at least insert the arguments, so that go to def etc. work within format macros + // We expand `format_args!("", arg1, arg2)` to + // `std::fmt::Arguments::new_v1(&[], &[&arg1, &arg2])`, + // which is still not really correct, but close enough for now + let mut args = Vec::new(); + let mut current = Vec::new(); + for tt in tt.token_trees.iter().cloned() { + match tt { + tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => { + args.push(tt::Subtree { delimiter: tt::Delimiter::None, token_trees: current }); + current = Vec::new(); + } + _ => { + current.push(tt); + } + } + } + if !current.is_empty() { + args.push(tt::Subtree { delimiter: tt::Delimiter::None, token_trees: current }); + } + if args.is_empty() { + return Err(mbe::ExpandError::NoMatchingRule); + } + let _format_string = args.remove(0); + let arg_tts = args.into_iter().flat_map(|arg| (quote! { & #arg , }).token_trees); let expanded = quote! { - std::fmt::Arguments::new_v1(&[], &[]) + std::fmt::Arguments::new_v1(&[], &[##arg_tts]) }; Ok(expanded) } @@ -324,4 +346,21 @@ mod tests { assert_eq!(expanded, r#"loop{"error!"}"#); } + + #[test] + fn test_format_args_expand() { + let expanded = expand_builtin_macro( + r#" + #[rustc_builtin_macro] + macro_rules! format_args { + ($fmt:expr) => ({ /* compiler built-in */ }); + ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) + } + format_args!("{} {:?}", arg1(a, b, c), arg2); +"#, + BuiltinFnLikeExpander::FormatArgs, + ); + + assert_eq!(expanded, r#"std::fmt::Arguments::new_v1(&[] ,&[&arg1(a,b,c),&arg2,])"#); + } } -- cgit v1.2.3