diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs index 5d770ecab0e..813c16c2084 100644 --- a/crates/hir_def/src/nameres/tests/macros.rs +++ b/crates/hir_def/src/nameres/tests/macros.rs @@ -1086,6 +1086,7 @@ struct B; #[test] fn eager_macro_correctly_resolves_dollar_crate() { + // MBE -> eager -> $crate::mbe check( r#" //- /lib.rs @@ -1108,9 +1109,37 @@ struct A; "#, expect![[r#" crate + A: t v inner: m "#]], ); + // eager -> MBE -> $crate::mbe + check( + r#" +//- /lib.rs +#[rustc_builtin_macro] +macro_rules! include { () => {} } - // FIXME: This currently fails. The result should contain `A: t v`. +#[macro_export] +macro_rules! inner { + () => { "inc.rs" }; +} + +macro_rules! n { + () => { + $crate::inner!() + }; +} + +include!(n!()); + +//- /inc.rs +struct A; +"#, + expect![[r#" + crate + A: t v + inner: m + "#]], + ); } diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index faeb6bebabb..66f7d8e3bc1 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs @@ -104,6 +104,7 @@ pub fn expand_eager_macro( resolver: &dyn Fn(ModPath) -> Option, diagnostic_sink: &mut dyn FnMut(mbe::ExpandError), ) -> Result, UnresolvedMacro> { + let hygiene = Hygiene::new(db, macro_call.file_id); let parsed_args = macro_call .value .token_tree() @@ -131,6 +132,7 @@ pub fn expand_eager_macro( let parsed_args = mbe::token_tree_to_syntax_node(&parsed_args, mbe::TopEntryPoint::Expr).0; let result = match eager_macro_recur( db, + &hygiene, InFile::new(arg_id.as_file(), parsed_args.syntax_node()), krate, resolver, @@ -193,12 +195,12 @@ fn lazy_expand( fn eager_macro_recur( db: &dyn AstDatabase, + hygiene: &Hygiene, curr: InFile, krate: CrateId, macro_resolver: &dyn Fn(ModPath) -> Option, mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError), ) -> Result, UnresolvedMacro> { - let hygiene = Hygiene::new(db, curr.file_id); let original = curr.value.clone_for_update(); let children = original.descendants().filter_map(ast::MacroCall::cast); @@ -243,7 +245,8 @@ fn eager_macro_recur( }; // replace macro inside - match eager_macro_recur(db, val, krate, macro_resolver, diagnostic_sink) { + let hygiene = Hygiene::new(db, val.file_id); + match eager_macro_recur(db, &hygiene, val, krate, macro_resolver, diagnostic_sink) { Ok(Ok(it)) => it, Ok(Err(err)) => return Ok(Err(err)), Err(err) => return Err(err), diff --git a/crates/ide_diagnostics/src/handlers/macro_error.rs b/crates/ide_diagnostics/src/handlers/macro_error.rs index 43b525133f1..a5bfb302d5e 100644 --- a/crates/ide_diagnostics/src/handlers/macro_error.rs +++ b/crates/ide_diagnostics/src/handlers/macro_error.rs @@ -38,6 +38,45 @@ macro_rules! compile_error { () => {} } ); } + #[test] + fn eager_macro_concat() { + // FIXME: this is incorrectly handling `$crate`, resulting in a wrong diagnostic. + // See: https://github.com/rust-analyzer/rust-analyzer/issues/10300 + + check_diagnostics( + r#" +//- /lib.rs crate:lib deps:core +use core::{panic, concat}; + +mod private { + pub use core::concat; +} + +macro_rules! m { + () => { + panic!(concat!($crate::private::concat!(""))); + }; +} + +fn f() { + m!(); + //^^^^ error: unresolved macro `$crate::private::concat!` +} + +//- /core.rs crate:core +#[macro_export] +#[rustc_builtin_macro] +macro_rules! concat { () => {} } + +pub macro panic { + ($msg:expr) => ( + $crate::panicking::panic_str($msg) + ), +} + "#, + ); + } + #[test] fn include_macro_should_allow_empty_content() { let mut config = DiagnosticsConfig::default();