Skip to content

Commit daa03b0

Browse files
committed
Auto merge of rust-lang#14800 - lowr:patch/macro-subns-and-prelude, r=Veykril
Expand more single ident macro calls upon item collection Addresses rust-lang/rust-analyzer#14781 (comment) I believe this (almost) brings the number of unresolved names back to pre-rust-lang#14781: |r-a version|`analysis-stats compiler/rustc` (rust-lang/rust@69fef92) | |---|---| |pre-rust-lang#14781 (b069eb7) | exprs: 2747778, ??ty: 122236 (4%), ?ty: 107826 (3%), !ty: 728 | | rust-lang#14781 (a7944a9) | exprs: 2713080, ??ty: 139651 (5%), ?ty: 114444 (4%), !ty: 730 | | with this fix | exprs: 2747871, ??ty: 122237 (4%), ?ty: 108171 (3%), !ty: 676 | (I haven't investigated on the increase in some numbers but hopefully not too much of a problem) This is only a temporary solution. The core problem is that we haven't fully implemented the textual scope of legacy macros. For example, we *have been* failing to resolve `foo` in the following snippet, even before rust-lang#14781 or after this patch. As noted in a FIXME, we need a way to resolve names in textual scope without eager expansion during item collection. ```rust //- /main.rs crate:main deps:lib lib::mk_foo!(); const A: i32 = foo!(); //^^^^^^ unresolved-macro-call //- /lib.rs crate:lib #[macro_export] macro_rules! mk_foo { () => { macro_rules! foo { () => { 42 } } } } ```
2 parents f38264f + e9ddb62 commit daa03b0

File tree

3 files changed

+61
-15
lines changed

3 files changed

+61
-15
lines changed

crates/hir-def/src/nameres/collector.rs

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ use crate::{
4444
mod_resolution::ModDir,
4545
path_resolution::ReachedFixedPoint,
4646
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind},
47-
BuiltinShadowMode, DefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode,
47+
sub_namespace_match, BuiltinShadowMode, DefMap, MacroSubNs, ModuleData, ModuleOrigin,
48+
ResolveMode,
4849
},
4950
path::{ImportAlias, ModPath, PathKind},
5051
per_ns::PerNs,
@@ -2141,26 +2142,34 @@ impl ModCollector<'_, '_> {
21412142

21422143
fn collect_macro_call(&mut self, mac: &MacroCall, container: ItemContainerId) {
21432144
let ast_id = AstIdWithPath::new(self.file_id(), mac.ast_id, ModPath::clone(&mac.path));
2145+
let db = self.def_collector.db;
21442146

2145-
// Case 1: try to resolve in legacy scope and expand macro_rules
2147+
// FIXME: Immediately expanding in "Case 1" is insufficient since "Case 2" may also define
2148+
// new legacy macros that create textual scopes. We need a way to resolve names in textual
2149+
// scopes without eager expansion.
2150+
2151+
// Case 1: try to resolve macro calls with single-segment name and expand macro_rules
21462152
if let Ok(res) = macro_call_as_call_id(
2147-
self.def_collector.db.upcast(),
2153+
db.upcast(),
21482154
&ast_id,
21492155
mac.expand_to,
21502156
self.def_collector.def_map.krate,
21512157
|path| {
21522158
path.as_ident().and_then(|name| {
2153-
self.def_collector.def_map.with_ancestor_maps(
2154-
self.def_collector.db,
2155-
self.module_id,
2156-
&mut |map, module| {
2157-
map[module]
2158-
.scope
2159-
.get_legacy_macro(name)
2160-
.and_then(|it| it.last())
2161-
.map(|&it| macro_id_to_def_id(self.def_collector.db, it))
2162-
},
2163-
)
2159+
let def_map = &self.def_collector.def_map;
2160+
def_map
2161+
.with_ancestor_maps(db, self.module_id, &mut |map, module| {
2162+
map[module].scope.get_legacy_macro(name)?.last().copied()
2163+
})
2164+
.or_else(|| def_map[self.module_id].scope.get(name).take_macros())
2165+
.or_else(|| def_map.macro_use_prelude.get(name).copied())
2166+
.filter(|&id| {
2167+
sub_namespace_match(
2168+
Some(MacroSubNs::from_id(db, id)),
2169+
Some(MacroSubNs::Bang),
2170+
)
2171+
})
2172+
.map(|it| macro_id_to_def_id(self.def_collector.db, it))
21642173
})
21652174
},
21662175
) {

crates/hir-def/src/nameres/path_resolution.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ impl ResolvePathResult {
5959
}
6060

6161
impl PerNs {
62-
fn filter_macro(mut self, db: &dyn DefDatabase, expected: Option<MacroSubNs>) -> Self {
62+
pub(super) fn filter_macro(
63+
mut self,
64+
db: &dyn DefDatabase,
65+
expected: Option<MacroSubNs>,
66+
) -> Self {
6367
self.macros = self.macros.filter(|&(id, _)| {
6468
let this = MacroSubNs::from_id(db, id);
6569
sub_namespace_match(Some(this), expected)

crates/hir-def/src/nameres/tests/macros.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,6 +1272,39 @@ pub mod prelude {
12721272
);
12731273
}
12741274

1275+
#[test]
1276+
fn macro_use_prelude_is_eagerly_expanded() {
1277+
// See FIXME in `ModCollector::collect_macro_call()`.
1278+
check(
1279+
r#"
1280+
//- /main.rs crate:main deps:lib
1281+
#[macro_use]
1282+
extern crate lib;
1283+
mk_foo!();
1284+
mod a {
1285+
foo!();
1286+
}
1287+
//- /lib.rs crate:lib
1288+
#[macro_export]
1289+
macro_rules! mk_foo {
1290+
() => {
1291+
macro_rules! foo {
1292+
() => { struct Ok; }
1293+
}
1294+
}
1295+
}
1296+
"#,
1297+
expect![[r#"
1298+
crate
1299+
a: t
1300+
lib: t
1301+
1302+
crate::a
1303+
Ok: t v
1304+
"#]],
1305+
);
1306+
}
1307+
12751308
#[test]
12761309
fn macro_sub_namespace() {
12771310
let map = compute_crate_def_map(

0 commit comments

Comments
 (0)