Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/nameres/path_resolution.rs')
-rw-r--r--crates/hir-def/src/nameres/path_resolution.rs45
1 files changed, 39 insertions, 6 deletions
diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index 5b454620e7..4740fd7f44 100644
--- a/crates/hir-def/src/nameres/path_resolution.rs
+++ b/crates/hir-def/src/nameres/path_resolution.rs
@@ -16,7 +16,7 @@ use hir_expand::name::Name;
use crate::{
db::DefDatabase,
item_scope::BUILTIN_SCOPE,
- nameres::{BuiltinShadowMode, DefMap},
+ nameres::{sub_namespace_match, BuiltinShadowMode, DefMap, MacroSubNs},
path::{ModPath, PathKind},
per_ns::PerNs,
visibility::{RawVisibility, Visibility},
@@ -58,6 +58,17 @@ impl ResolvePathResult {
}
}
+impl PerNs {
+ fn filter_macro(mut self, db: &dyn DefDatabase, expected: Option<MacroSubNs>) -> Self {
+ self.macros = self.macros.filter(|&(id, _)| {
+ let this = MacroSubNs::from_id(db, id);
+ sub_namespace_match(Some(this), expected)
+ });
+
+ self
+ }
+}
+
impl DefMap {
pub(super) fn resolve_name_in_extern_prelude(
&self,
@@ -83,7 +94,7 @@ impl DefMap {
let mut vis = match visibility {
RawVisibility::Module(path) => {
let (result, remaining) =
- self.resolve_path(db, original_module, path, BuiltinShadowMode::Module);
+ self.resolve_path(db, original_module, path, BuiltinShadowMode::Module, None);
if remaining.is_some() {
return None;
}
@@ -124,6 +135,9 @@ impl DefMap {
mut original_module: LocalModuleId,
path: &ModPath,
shadow: BuiltinShadowMode,
+ // Pass `MacroSubNs` if we know we're resolving macro names and which kind of macro we're
+ // resolving them to. Pass `None` otherwise, e.g. when we're resolving import paths.
+ expected_macro_subns: Option<MacroSubNs>,
) -> ResolvePathResult {
let mut result = ResolvePathResult::empty(ReachedFixedPoint::No);
@@ -136,6 +150,7 @@ impl DefMap {
original_module,
path,
shadow,
+ expected_macro_subns,
);
// Merge `new` into `result`.
@@ -169,6 +184,7 @@ impl DefMap {
original_module: LocalModuleId,
path: &ModPath,
shadow: BuiltinShadowMode,
+ expected_macro_subns: Option<MacroSubNs>,
) -> ResolvePathResult {
let graph = db.crate_graph();
let _cx = stdx::panic_context::enter(format!(
@@ -220,7 +236,13 @@ impl DefMap {
if path.segments().len() == 1 { shadow } else { BuiltinShadowMode::Module };
tracing::debug!("resolving {:?} in module", segment);
- self.resolve_name_in_module(db, original_module, segment, prefer_module)
+ self.resolve_name_in_module(
+ db,
+ original_module,
+ segment,
+ prefer_module,
+ expected_macro_subns,
+ )
}
PathKind::Super(lvl) => {
let mut module = original_module;
@@ -245,6 +267,7 @@ impl DefMap {
block.parent.local_id,
&new_path,
shadow,
+ expected_macro_subns,
);
}
None => {
@@ -303,7 +326,12 @@ impl DefMap {
);
tracing::debug!("resolving {:?} in other crate", path);
let defp_map = module.def_map(db);
- let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow);
+ // Macro sub-namespaces only matter when resolving single-segment paths
+ // because `macro_use` and other preludes should be taken into account. At
+ // this point, we know we're resolving a multi-segment path so macro kind
+ // expectation is discarded.
+ let (def, s) =
+ defp_map.resolve_path(db, module.local_id, &path, shadow, None);
return ResolvePathResult::with(
def,
ReachedFixedPoint::Yes,
@@ -381,6 +409,7 @@ impl DefMap {
module: LocalModuleId,
name: &Name,
shadow: BuiltinShadowMode,
+ expected_macro_subns: Option<MacroSubNs>,
) -> PerNs {
// Resolve in:
// - legacy scope of macro
@@ -392,8 +421,12 @@ impl DefMap {
.get_legacy_macro(name)
// FIXME: shadowing
.and_then(|it| it.last())
- .map_or_else(PerNs::none, |&m| PerNs::macros(m, Visibility::Public));
- let from_scope = self[module].scope.get(name);
+ .copied()
+ .filter(|&id| {
+ sub_namespace_match(Some(MacroSubNs::from_id(db, id)), expected_macro_subns)
+ })
+ .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public));
+ let from_scope = self[module].scope.get(name).filter_macro(db, expected_macro_subns);
let from_builtin = match self.block {
Some(_) => {
// Only resolve to builtins in the root `DefMap`.