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.rs101
1 files changed, 78 insertions, 23 deletions
diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index a49155d878..74ce33a641 100644
--- a/crates/hir-def/src/nameres/path_resolution.rs
+++ b/crates/hir-def/src/nameres/path_resolution.rs
@@ -17,14 +17,17 @@ use hir_expand::{
name::Name,
};
use span::Edition;
-use triomphe::Arc;
+use stdx::TupleExt;
use crate::{
AdtId, LocalModuleId, ModuleDefId,
db::DefDatabase,
item_scope::{BUILTIN_SCOPE, ImportOrExternCrate},
item_tree::FieldsShape,
- nameres::{BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, sub_namespace_match},
+ nameres::{
+ BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, crate_def_map,
+ sub_namespace_match,
+ },
per_ns::PerNs,
visibility::{RawVisibility, Visibility},
};
@@ -44,6 +47,7 @@ pub(super) enum ReachedFixedPoint {
#[derive(Debug, Clone)]
pub(super) struct ResolvePathResult {
pub(super) resolved_def: PerNs,
+ /// The index of the last resolved segment, or `None` if the full path has been resolved.
pub(super) segment_index: Option<usize>,
pub(super) reached_fixedpoint: ReachedFixedPoint,
pub(super) prefix_info: ResolvePathResultPrefixInfo,
@@ -173,7 +177,6 @@ impl DefMap {
return result;
}
- let mut arc;
let mut current_map = self;
let mut merge = |new: ResolvePathResult| {
@@ -195,8 +198,7 @@ impl DefMap {
Some(block) if original_module == Self::ROOT => {
// Block modules "inherit" names from its parent module.
original_module = block.parent.local_id;
- arc = block.parent.def_map(db, current_map.krate);
- current_map = &arc;
+ current_map = block.parent.def_map(db, current_map.krate);
}
// Proper (non-block) modules, including those in block `DefMap`s, don't.
_ => {
@@ -204,8 +206,7 @@ impl DefMap {
// A module inside a block. Do not resolve items declared in upper blocks, but we do need to get
// the prelude items (which are not inserted into blocks because they can be overridden there).
original_module = Self::ROOT;
- arc = db.crate_def_map(self.krate);
- current_map = &arc;
+ current_map = crate_def_map(db, self.krate);
let new = current_map.resolve_path_fp_in_all_preludes(
local_def_map,
@@ -253,7 +254,7 @@ impl DefMap {
cov_mark::hit!(macro_dollar_crate_self);
PerNs::types(self.crate_root().into(), Visibility::Public, None)
} else {
- let def_map = db.crate_def_map(krate);
+ let def_map = crate_def_map(db, krate);
let module = def_map.module_id(Self::ROOT);
cov_mark::hit!(macro_dollar_crate_other);
PerNs::types(module.into(), Visibility::Public, None)
@@ -312,7 +313,7 @@ impl DefMap {
// Adjust `local_id` to `self`, i.e. the nearest non-block module.
if def_map.module_id(local_id).is_block_module() {
(ext, local_id) = adjust_to_nearest_non_block_module(db, def_map, local_id);
- def_map = &ext;
+ def_map = ext;
}
// Go up the module tree but skip block modules as `super` always refers to the
@@ -325,7 +326,7 @@ impl DefMap {
if def_map.module_id(local_id).is_block_module() {
(ext, local_id) =
adjust_to_nearest_non_block_module(db, def_map, local_id);
- def_map = &ext;
+ def_map = ext;
}
} else {
stdx::always!(def_map.block.is_none());
@@ -364,7 +365,15 @@ impl DefMap {
},
};
- self.resolve_remaining_segments(segments, curr_per_ns, path, db, shadow, original_module)
+ self.resolve_remaining_segments(
+ db,
+ mode,
+ segments,
+ curr_per_ns,
+ path,
+ shadow,
+ original_module,
+ )
}
/// Resolves a path only in the preludes, without accounting for item scopes.
@@ -413,7 +422,15 @@ impl DefMap {
}
};
- self.resolve_remaining_segments(segments, curr_per_ns, path, db, shadow, original_module)
+ self.resolve_remaining_segments(
+ db,
+ mode,
+ segments,
+ curr_per_ns,
+ path,
+ shadow,
+ original_module,
+ )
}
/// 2018-style absolute path -- only extern prelude
@@ -441,10 +458,11 @@ impl DefMap {
fn resolve_remaining_segments<'a>(
&self,
+ db: &dyn DefDatabase,
+ mode: ResolveMode,
mut segments: impl Iterator<Item = (usize, &'a Name)>,
mut curr_per_ns: PerNs,
path: &ModPath,
- db: &dyn DefDatabase,
shadow: BuiltinShadowMode,
original_module: LocalModuleId,
) -> ResolvePathResult {
@@ -465,6 +483,7 @@ impl DefMap {
curr_per_ns = match curr.def {
ModuleDefId::ModuleId(module) => {
if module.krate != self.krate {
+ // FIXME: Inefficient
let path = ModPath::from_segments(
PathKind::SELF,
path.segments()[i..].iter().cloned(),
@@ -478,7 +497,7 @@ impl DefMap {
let resolution = defp_map.resolve_path_fp_with_macro(
LocalDefMap::EMPTY,
db,
- ResolveMode::Other,
+ mode,
module.local_id,
&path,
shadow,
@@ -553,6 +572,44 @@ impl DefMap {
),
};
}
+ def @ ModuleDefId::TraitId(t) if mode == ResolveMode::Import => {
+ // FIXME: Implement this correctly
+ // We can't actually call `trait_items`, the reason being that if macro calls
+ // occur, they will call back into the def map which we might be computing right
+ // now resulting in a cycle.
+ // To properly implement this, trait item collection needs to be done in def map
+ // collection...
+ let item =
+ if true { None } else { db.trait_items(t).assoc_item_by_name(segment) };
+ return match item {
+ Some(item) => ResolvePathResult::new(
+ match item {
+ crate::AssocItemId::FunctionId(function_id) => PerNs::values(
+ function_id.into(),
+ curr.vis,
+ curr.import.and_then(|it| it.import_or_glob()),
+ ),
+ crate::AssocItemId::ConstId(const_id) => PerNs::values(
+ const_id.into(),
+ curr.vis,
+ curr.import.and_then(|it| it.import_or_glob()),
+ ),
+ crate::AssocItemId::TypeAliasId(type_alias_id) => {
+ PerNs::types(type_alias_id.into(), curr.vis, curr.import)
+ }
+ },
+ ReachedFixedPoint::Yes,
+ segments.next().map(TupleExt::head),
+ ResolvePathResultPrefixInfo::default(),
+ ),
+ None => ResolvePathResult::new(
+ PerNs::types(def, curr.vis, curr.import),
+ ReachedFixedPoint::Yes,
+ Some(i),
+ ResolvePathResultPrefixInfo::default(),
+ ),
+ };
+ }
s => {
// could be an inherent method call in UFCS form
// (`Struct::method`), or some other kind of associated item
@@ -715,7 +772,7 @@ impl DefMap {
} else {
// Extend lifetime
keep = prelude.def_map(db);
- &keep
+ keep
};
def_map[prelude.local_id].scope.get(name)
} else {
@@ -725,25 +782,23 @@ impl DefMap {
}
/// Given a block module, returns its nearest non-block module and the `DefMap` it belongs to.
-fn adjust_to_nearest_non_block_module(
- db: &dyn DefDatabase,
- def_map: &DefMap,
+fn adjust_to_nearest_non_block_module<'db>(
+ db: &'db dyn DefDatabase,
+ def_map: &'db DefMap,
mut local_id: LocalModuleId,
-) -> (Arc<DefMap>, LocalModuleId) {
+) -> (&'db DefMap, LocalModuleId) {
// INVARIANT: `local_id` in `def_map` must be a block module.
stdx::always!(def_map.module_id(local_id).is_block_module());
- let mut ext;
// This needs to be a local variable due to our mighty lifetime.
let mut def_map = def_map;
loop {
let BlockInfo { parent, .. } = def_map.block.expect("block module without parent module");
- ext = parent.def_map(db, def_map.krate);
- def_map = &ext;
+ def_map = parent.def_map(db, def_map.krate);
local_id = parent.local_id;
if !parent.is_block_module() {
- return (ext, local_id);
+ return (def_map, local_id);
}
}
}