diff --git a/crates/hir_def/src/macro_expansion_tests.rs b/crates/hir_def/src/macro_expansion_tests.rs
index 9c91ea8a7abd..c317dc27a583 100644
--- a/crates/hir_def/src/macro_expansion_tests.rs
+++ b/crates/hir_def/src/macro_expansion_tests.rs
@@ -46,17 +46,19 @@ fn check(ra_fixture: &str, mut expect: Expect) {
let mut expansions = Vec::new();
for macro_call in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) {
let macro_call = InFile::new(source.file_id, ¯o_call);
+ let mut error = None;
let macro_call_id = macro_call
.as_call_id_with_errors(
&db,
krate,
|path| resolver.resolve_path_as_macro(&db, &path),
- &mut |err| panic!("{}", err),
+ &mut |err| error = Some(err),
)
.unwrap()
.unwrap();
let macro_file = MacroFile { macro_call_id };
- let expansion_result = db.parse_macro_expansion(macro_file);
+ let mut expansion_result = db.parse_macro_expansion(macro_file);
+ expansion_result.err = expansion_result.err.or(error);
expansions.push((macro_call.value.clone(), expansion_result));
}
diff --git a/crates/hir_def/src/macro_expansion_tests/builtin.rs b/crates/hir_def/src/macro_expansion_tests/builtin.rs
index c2b900b9df39..1b25caa0ff1b 100644
--- a/crates/hir_def/src/macro_expansion_tests/builtin.rs
+++ b/crates/hir_def/src/macro_expansion_tests/builtin.rs
@@ -119,3 +119,154 @@ fn main() { ""; }
"##]],
);
}
+
+#[test]
+fn test_assert_expand() {
+ check(
+ r#"
+#[rustc_builtin_macro]
+macro_rules! assert {
+ ($cond:expr) => ({ /* compiler built-in */ });
+ ($cond:expr, $($args:tt)*) => ({ /* compiler built-in */ })
+}
+
+fn main() {
+ assert!(true, "{} {:?}", arg1(a, b, c), arg2);
+}
+"#,
+ expect![[r##"
+#[rustc_builtin_macro]
+macro_rules! assert {
+ ($cond:expr) => ({ /* compiler built-in */ });
+ ($cond:expr, $($args:tt)*) => ({ /* compiler built-in */ })
+}
+
+fn main() {
+ {
+ if !true {
+ $crate::panic!("{} {:?}", arg1(a, b, c), arg2);
+ }
+ };
+}
+"##]],
+ );
+}
+
+#[test]
+fn test_compile_error_expand() {
+ check(
+ r#"
+#[rustc_builtin_macro]
+macro_rules! compile_error {
+ ($msg:expr) => ({ /* compiler built-in */ });
+ ($msg:expr,) => ({ /* compiler built-in */ })
+}
+
+// This expands to nothing (since it's in item position), but emits an error.
+compile_error!("error!");
+"#,
+ expect![[r##"
+#[rustc_builtin_macro]
+macro_rules! compile_error {
+ ($msg:expr) => ({ /* compiler built-in */ });
+ ($msg:expr,) => ({ /* compiler built-in */ })
+}
+
+/* error: error! */
+"##]],
+ );
+}
+
+#[test]
+fn test_format_args_expand() {
+ 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!("{} {:?}", arg1(a, b, c), arg2);
+}
+"#,
+ expect![[r##"
+#[rustc_builtin_macro]
+macro_rules! format_args {
+ ($fmt:expr) => ({ /* compiler built-in */ });
+ ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
+}
+
+fn main() {
+ unsafe {
+ std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(arg1(a, b, c)), std::fmt::Display::fmt), std::fmt::ArgumentV1::new(&(arg2), std::fmt::Display::fmt), ])
+ };
+}
+"##]],
+ );
+}
+
+#[test]
+fn test_format_args_expand_with_comma_exprs() {
+ 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!("{} {:?}", a::(), b);
+}
+"#,
+ expect![[r##"
+#[rustc_builtin_macro]
+macro_rules! format_args {
+ ($fmt:expr) => ({ /* compiler built-in */ });
+ ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
+}
+
+fn main() {
+ unsafe {
+ std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a::()), std::fmt::Display::fmt), std::fmt::ArgumentV1::new(&(b), std::fmt::Display::fmt), ])
+ };
+}
+"##]],
+ );
+}
+
+#[test]
+fn test_format_args_expand_with_broken_member_access() {
+ check(
+ r#"
+#[rustc_builtin_macro]
+macro_rules! format_args {
+ ($fmt:expr) => ({ /* compiler built-in */ });
+ ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
+}
+
+fn main() {
+ let _ =
+ // +errors
+ format_args!("{} {:?}", a.);
+}
+"#,
+ expect![[r##"
+#[rustc_builtin_macro]
+macro_rules! format_args {
+ ($fmt:expr) => ({ /* compiler built-in */ });
+ ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
+}
+
+fn main() {
+ let _ =
+ /* parse error: expected field name or number */
+unsafe {
+ std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a.), std::fmt::Display::fmt), ])
+ };
+}
+"##]],
+ );
+}
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 55dc665c5d78..f988ffff09ee 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -669,88 +669,6 @@ mod tests {
expect.assert_eq(&expansion);
}
- #[test]
- fn test_assert_expand() {
- check_expansion(
- r#"
- #[rustc_builtin_macro]
- macro_rules! assert {
- ($cond:expr) => ({ /* compiler built-in */ });
- ($cond:expr, $($args:tt)*) => ({ /* compiler built-in */ })
- }
- assert!(true, "{} {:?}", arg1(a, b, c), arg2);
- "#,
- expect![[r#"{if!true{$crate::panic!("{} {:?}",arg1(a,b,c),arg2);}}"#]],
- );
- }
-
- #[test]
- fn test_compile_error_expand() {
- check_expansion(
- r#"
- #[rustc_builtin_macro]
- macro_rules! compile_error {
- ($msg:expr) => ({ /* compiler built-in */ });
- ($msg:expr,) => ({ /* compiler built-in */ })
- }
- compile_error!("error!");
- "#,
- // This expands to nothing (since it's in item position), but emits an error.
- expect![[""]],
- );
- }
-
- #[test]
- fn test_format_args_expand() {
- check_expansion(
- 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);
- "#,
- expect![[
- r#"unsafe{std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])}"#
- ]],
- );
- }
-
- #[test]
- fn test_format_args_expand_with_comma_exprs() {
- check_expansion(
- r#"
- #[rustc_builtin_macro]
- macro_rules! format_args {
- ($fmt:expr) => ({ /* compiler built-in */ });
- ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
- }
- format_args!("{} {:?}", a::(), b);
- "#,
- expect![[
- r#"unsafe{std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a::()),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(b),std::fmt::Display::fmt),])}"#
- ]],
- );
- }
-
- #[test]
- fn test_format_args_expand_with_broken_member_access() {
- check_expansion(
- r#"
- #[rustc_builtin_macro]
- macro_rules! format_args {
- ($fmt:expr) => ({ /* compiler built-in */ });
- ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
- }
- format_args!("{} {:?}", a.);
- "#,
- expect![[
- r#"unsafe{std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a.),std::fmt::Display::fmt),])}"#
- ]],
- );
- }
-
#[test]
fn test_include_bytes_expand() {
check_expansion(