Skip to content

Commit 8d32301

Browse files
committed
Consider macro sub-namespace during name resolution
1 parent ff26ae1 commit 8d32301

File tree

15 files changed

+236
-36
lines changed

15 files changed

+236
-36
lines changed

crates/hir-def/src/body/lower.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use crate::{
3737
item_scope::BuiltinShadowMode,
3838
lang_item::LangItem,
3939
lower::LowerCtx,
40-
nameres::DefMap,
40+
nameres::{DefMap, MacroSubNs},
4141
path::{GenericArgs, Path},
4242
type_ref::{Mutability, Rawness, TypeRef},
4343
AdtId, BlockId, BlockLoc, ModuleDefId, UnresolvedMacro,
@@ -800,7 +800,13 @@ impl ExprCollector<'_> {
800800
let module = self.expander.module.local_id;
801801
let res = self.expander.enter_expand(self.db, mcall, |path| {
802802
self.def_map
803-
.resolve_path(self.db, module, &path, crate::item_scope::BuiltinShadowMode::Other)
803+
.resolve_path(
804+
self.db,
805+
module,
806+
&path,
807+
crate::item_scope::BuiltinShadowMode::Other,
808+
Some(MacroSubNs::Bang),
809+
)
804810
.0
805811
.take_macros()
806812
});
@@ -1056,6 +1062,7 @@ impl ExprCollector<'_> {
10561062
self.expander.module.local_id,
10571063
&name.clone().into(),
10581064
BuiltinShadowMode::Other,
1065+
None,
10591066
);
10601067
match resolved.take_values() {
10611068
Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())),

crates/hir-def/src/data.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::{
2222
attr_resolution::ResolvedAttr,
2323
diagnostics::DefDiagnostic,
2424
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind},
25-
DefMap,
25+
DefMap, MacroSubNs,
2626
},
2727
type_ref::{TraitRef, TypeBound, TypeRef},
2828
visibility::RawVisibility,
@@ -673,6 +673,7 @@ impl<'a> AssocItemCollector<'a> {
673673
module,
674674
&path,
675675
crate::item_scope::BuiltinShadowMode::Other,
676+
Some(MacroSubNs::Bang),
676677
)
677678
.0
678679
.take_macros()

crates/hir-def/src/find_path.rs

+1
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ mod tests {
543543
module.local_id,
544544
&mod_path,
545545
crate::item_scope::BuiltinShadowMode::Module,
546+
None,
546547
)
547548
.0
548549
.take_types()

crates/hir-def/src/generics.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::{
2222
dyn_map::{keys, DynMap},
2323
expander::Expander,
2424
lower::LowerCtx,
25-
nameres::DefMap,
25+
nameres::{DefMap, MacroSubNs},
2626
src::{HasChildSource, HasSource},
2727
type_ref::{LifetimeRef, TypeBound, TypeRef},
2828
AdtId, ConstParamId, GenericDefId, HasModule, LifetimeParamId, LocalLifetimeParamId,
@@ -361,6 +361,7 @@ impl GenericParams {
361361
module,
362362
&path,
363363
crate::item_scope::BuiltinShadowMode::Other,
364+
Some(MacroSubNs::Bang),
364365
)
365366
.0
366367
.take_macros()

crates/hir-def/src/macro_expansion_tests/mod.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,13 @@ use syntax::{
3333
use tt::token_id::{Subtree, TokenId};
3434

3535
use crate::{
36-
db::DefDatabase, macro_id_to_def_id, nameres::ModuleSource, resolver::HasResolver,
37-
src::HasSource, test_db::TestDB, AdtId, AsMacroCall, Lookup, ModuleDefId,
36+
db::DefDatabase,
37+
macro_id_to_def_id,
38+
nameres::{MacroSubNs, ModuleSource},
39+
resolver::HasResolver,
40+
src::HasSource,
41+
test_db::TestDB,
42+
AdtId, AsMacroCall, Lookup, ModuleDefId,
3843
};
3944

4045
#[track_caller]
@@ -127,7 +132,9 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
127132
let macro_call = InFile::new(source.file_id, &macro_call);
128133
let res = macro_call
129134
.as_call_id_with_errors(&db, krate, |path| {
130-
resolver.resolve_path_as_macro(&db, &path).map(|it| macro_id_to_def_id(&db, it))
135+
resolver
136+
.resolve_path_as_macro(&db, &path, Some(MacroSubNs::Bang))
137+
.map(|it| macro_id_to_def_id(&db, it))
131138
})
132139
.unwrap();
133140
let macro_call_id = res.value.unwrap();

crates/hir-def/src/nameres.rs

+58-4
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ mod tests;
5959

6060
use std::{cmp::Ord, ops::Deref};
6161

62-
use base_db::{CrateId, Edition, FileId};
62+
use base_db::{CrateId, Edition, FileId, ProcMacroKind};
6363
use hir_expand::{name::Name, InFile, MacroCallId, MacroDefId};
6464
use itertools::Itertools;
6565
use la_arena::Arena;
@@ -77,7 +77,8 @@ use crate::{
7777
path::ModPath,
7878
per_ns::PerNs,
7979
visibility::Visibility,
80-
AstId, BlockId, BlockLoc, FunctionId, LocalModuleId, MacroId, ModuleId, ProcMacroId,
80+
AstId, BlockId, BlockLoc, FunctionId, LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId,
81+
ProcMacroId,
8182
};
8283

8384
/// Contains the results of (early) name resolution.
@@ -380,9 +381,16 @@ impl DefMap {
380381
original_module: LocalModuleId,
381382
path: &ModPath,
382383
shadow: BuiltinShadowMode,
384+
expected_macro_subns: Option<MacroSubNs>,
383385
) -> (PerNs, Option<usize>) {
384-
let res =
385-
self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path, shadow);
386+
let res = self.resolve_path_fp_with_macro(
387+
db,
388+
ResolveMode::Other,
389+
original_module,
390+
path,
391+
shadow,
392+
expected_macro_subns,
393+
);
386394
(res.resolved_def, res.segment_index)
387395
}
388396

@@ -399,6 +407,7 @@ impl DefMap {
399407
original_module,
400408
path,
401409
shadow,
410+
None, // Currently this function isn't used for macro resolution.
402411
);
403412
(res.resolved_def, res.segment_index)
404413
}
@@ -568,3 +577,48 @@ pub enum ModuleSource {
568577
Module(ast::Module),
569578
BlockExpr(ast::BlockExpr),
570579
}
580+
581+
/// See `sub_namespace_match()`.
582+
#[derive(Clone, Copy, PartialEq, Eq)]
583+
pub enum MacroSubNs {
584+
/// Function-like macros, suffixed with `!`.
585+
Bang,
586+
/// Macros inside attributes, i.e. attribute macros and derive macros.
587+
Attr,
588+
}
589+
590+
impl MacroSubNs {
591+
fn from_id(db: &dyn DefDatabase, macro_id: MacroId) -> Self {
592+
let expander = match macro_id {
593+
MacroId::Macro2Id(it) => it.lookup(db).expander,
594+
MacroId::MacroRulesId(it) => it.lookup(db).expander,
595+
MacroId::ProcMacroId(it) => {
596+
return match it.lookup(db).kind {
597+
ProcMacroKind::CustomDerive | ProcMacroKind::Attr => Self::Attr,
598+
ProcMacroKind::FuncLike => Self::Bang,
599+
};
600+
}
601+
};
602+
603+
// Eager macros aren't *guaranteed* to be bang macros, but they *are* all bang macros currently.
604+
match expander {
605+
MacroExpander::Declarative
606+
| MacroExpander::BuiltIn(_)
607+
| MacroExpander::BuiltInEager(_) => Self::Bang,
608+
MacroExpander::BuiltInAttr(_) | MacroExpander::BuiltInDerive(_) => Self::Attr,
609+
}
610+
}
611+
}
612+
613+
/// Quoted from [rustc]:
614+
/// Macro namespace is separated into two sub-namespaces, one for bang macros and
615+
/// one for attribute-like macros (attributes, derives).
616+
/// We ignore resolutions from one sub-namespace when searching names in scope for another.
617+
///
618+
/// [rustc]: https://github.com/rust-lang/rust/blob/1.69.0/compiler/rustc_resolve/src/macros.rs#L75
619+
fn sub_namespace_match(candidate: Option<MacroSubNs>, expected: Option<MacroSubNs>) -> bool {
620+
match (candidate, expected) {
621+
(Some(candidate), Some(expected)) => candidate == expected,
622+
_ => true,
623+
}
624+
}

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::{
1414
AstIdWithPath, LocalModuleId, UnresolvedMacro,
1515
};
1616

17-
use super::DefMap;
17+
use super::{DefMap, MacroSubNs};
1818

1919
pub enum ResolvedAttr {
2020
/// Attribute resolved to an attribute macro.
@@ -43,9 +43,12 @@ impl DefMap {
4343
original_module,
4444
&ast_id.path,
4545
BuiltinShadowMode::Module,
46+
Some(MacroSubNs::Attr),
4647
);
4748
let def = match resolved_res.resolved_def.take_macros() {
4849
Some(def) => {
50+
// `MacroSubNs` is just a hint, so the path may still resolve to a custom derive
51+
// macro, or even function-like macro when the path is qualified.
4952
if def.is_attribute(db) {
5053
def
5154
} else {

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

+18-3
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use crate::{
4444
mod_resolution::ModDir,
4545
path_resolution::ReachedFixedPoint,
4646
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind},
47-
BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode,
47+
BuiltinShadowMode, DefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode,
4848
},
4949
path::{ImportAlias, ModPath, PathKind},
5050
per_ns::PerNs,
@@ -549,8 +549,13 @@ impl DefCollector<'_> {
549549
};
550550
let path = ModPath::from_segments(path_kind, [krate, name![prelude], edition]);
551551

552-
let (per_ns, _) =
553-
self.def_map.resolve_path(self.db, self.def_map.root, &path, BuiltinShadowMode::Other);
552+
let (per_ns, _) = self.def_map.resolve_path(
553+
self.db,
554+
self.def_map.root,
555+
&path,
556+
BuiltinShadowMode::Other,
557+
None,
558+
);
554559

555560
match per_ns.types {
556561
Some((ModuleDefId::ModuleId(m), _)) => {
@@ -796,6 +801,7 @@ impl DefCollector<'_> {
796801
module_id,
797802
&import.path,
798803
BuiltinShadowMode::Module,
804+
None, // An import may resolve to any kind of macro.
799805
);
800806

801807
let def = res.resolved_def;
@@ -1093,14 +1099,22 @@ impl DefCollector<'_> {
10931099
resolved.push((directive.module_id, directive.depth, directive.container, call_id));
10941100
};
10951101
let mut res = ReachedFixedPoint::Yes;
1102+
// Retain unresolved macros after this round of resolution.
10961103
macros.retain(|directive| {
1104+
let subns = match &directive.kind {
1105+
MacroDirectiveKind::FnLike { .. } => MacroSubNs::Bang,
1106+
MacroDirectiveKind::Attr { .. } | MacroDirectiveKind::Derive { .. } => {
1107+
MacroSubNs::Attr
1108+
}
1109+
};
10971110
let resolver = |path| {
10981111
let resolved_res = self.def_map.resolve_path_fp_with_macro(
10991112
self.db,
11001113
ResolveMode::Other,
11011114
directive.module_id,
11021115
&path,
11031116
BuiltinShadowMode::Module,
1117+
Some(subns),
11041118
);
11051119
resolved_res
11061120
.resolved_def
@@ -1419,6 +1433,7 @@ impl DefCollector<'_> {
14191433
directive.module_id,
14201434
&path,
14211435
BuiltinShadowMode::Module,
1436+
Some(MacroSubNs::Bang),
14221437
);
14231438
resolved_res
14241439
.resolved_def

0 commit comments

Comments
 (0)