mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 09:27:27 +00:00
Merge #11354
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:
commit
15d8f0c466
3 changed files with 74 additions and 3 deletions
|
@ -1086,6 +1086,7 @@ struct B;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn eager_macro_correctly_resolves_dollar_crate() {
|
fn eager_macro_correctly_resolves_dollar_crate() {
|
||||||
|
// MBE -> eager -> $crate::mbe
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
//- /lib.rs
|
//- /lib.rs
|
||||||
|
@ -1108,9 +1109,37 @@ struct A;
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
crate
|
crate
|
||||||
|
A: t v
|
||||||
inner: m
|
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
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,7 @@ pub fn expand_eager_macro(
|
||||||
resolver: &dyn Fn(ModPath) -> Option<MacroDefId>,
|
resolver: &dyn Fn(ModPath) -> Option<MacroDefId>,
|
||||||
diagnostic_sink: &mut dyn FnMut(mbe::ExpandError),
|
diagnostic_sink: &mut dyn FnMut(mbe::ExpandError),
|
||||||
) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
|
) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
|
||||||
|
let hygiene = Hygiene::new(db, macro_call.file_id);
|
||||||
let parsed_args = macro_call
|
let parsed_args = macro_call
|
||||||
.value
|
.value
|
||||||
.token_tree()
|
.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 parsed_args = mbe::token_tree_to_syntax_node(&parsed_args, mbe::TopEntryPoint::Expr).0;
|
||||||
let result = match eager_macro_recur(
|
let result = match eager_macro_recur(
|
||||||
db,
|
db,
|
||||||
|
&hygiene,
|
||||||
InFile::new(arg_id.as_file(), parsed_args.syntax_node()),
|
InFile::new(arg_id.as_file(), parsed_args.syntax_node()),
|
||||||
krate,
|
krate,
|
||||||
resolver,
|
resolver,
|
||||||
|
@ -193,12 +195,12 @@ fn lazy_expand(
|
||||||
|
|
||||||
fn eager_macro_recur(
|
fn eager_macro_recur(
|
||||||
db: &dyn AstDatabase,
|
db: &dyn AstDatabase,
|
||||||
|
hygiene: &Hygiene,
|
||||||
curr: InFile<SyntaxNode>,
|
curr: InFile<SyntaxNode>,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
macro_resolver: &dyn Fn(ModPath) -> Option<MacroDefId>,
|
macro_resolver: &dyn Fn(ModPath) -> Option<MacroDefId>,
|
||||||
mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError),
|
mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError),
|
||||||
) -> Result<Result<SyntaxNode, ErrorEmitted>, UnresolvedMacro> {
|
) -> Result<Result<SyntaxNode, ErrorEmitted>, UnresolvedMacro> {
|
||||||
let hygiene = Hygiene::new(db, curr.file_id);
|
|
||||||
let original = curr.value.clone_for_update();
|
let original = curr.value.clone_for_update();
|
||||||
|
|
||||||
let children = original.descendants().filter_map(ast::MacroCall::cast);
|
let children = original.descendants().filter_map(ast::MacroCall::cast);
|
||||||
|
@ -243,7 +245,8 @@ fn eager_macro_recur(
|
||||||
};
|
};
|
||||||
|
|
||||||
// replace macro inside
|
// 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(Ok(it)) => it,
|
||||||
Ok(Err(err)) => return Ok(Err(err)),
|
Ok(Err(err)) => return Ok(Err(err)),
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
|
|
|
@ -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]
|
#[test]
|
||||||
fn include_macro_should_allow_empty_content() {
|
fn include_macro_should_allow_empty_content() {
|
||||||
let mut config = DiagnosticsConfig::default();
|
let mut config = DiagnosticsConfig::default();
|
||||||
|
|
Loading…
Reference in a new issue