11354: fix: More correct `$crate` handling in eager macros r=jonas-schievink a=jonas-schievink

Fixes a few of the additional bugs in https://github.com/rust-analyzer/rust-analyzer/issues/10300, but not yet that issue itself.

bors r+

Co-authored-by: Jonas Schievink <jonas.schievink@ferrous-systems.com>
This commit is contained in:
bors[bot] 2022-01-27 15:59:18 +00:00 committed by GitHub
commit 15d8f0c466
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 3 deletions

View file

@ -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
"#]],
);
}

View file

@ -104,6 +104,7 @@ pub fn expand_eager_macro(
resolver: &dyn Fn(ModPath) -> Option<MacroDefId>,
diagnostic_sink: &mut dyn FnMut(mbe::ExpandError),
) -> Result<Result<MacroCallId, ErrorEmitted>, 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<SyntaxNode>,
krate: CrateId,
macro_resolver: &dyn Fn(ModPath) -> Option<MacroDefId>,
mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError),
) -> Result<Result<SyntaxNode, ErrorEmitted>, 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),

View file

@ -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();