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.rs120
1 files changed, 72 insertions, 48 deletions
diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index 47c08d3d1d..f8b2c73a8f 100644
--- a/crates/hir-def/src/nameres/path_resolution.rs
+++ b/crates/hir-def/src/nameres/path_resolution.rs
@@ -11,19 +11,22 @@
//! `ReachedFixedPoint` signals about this.
use either::Either;
-use hir_expand::{name::Name, Lookup};
+use hir_expand::{
+ Lookup,
+ mod_path::{ModPath, PathKind},
+ name::Name,
+};
use span::Edition;
use triomphe::Arc;
use crate::{
+ AdtId, LocalModuleId, ModuleDefId,
db::DefDatabase,
- item_scope::{ImportOrExternCrate, BUILTIN_SCOPE},
+ item_scope::{BUILTIN_SCOPE, ImportOrExternCrate},
item_tree::FieldsShape,
- nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs},
- path::{ModPath, PathKind},
+ nameres::{BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, sub_namespace_match},
per_ns::PerNs,
visibility::{RawVisibility, Visibility},
- AdtId, LocalModuleId, ModuleDefId,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -91,6 +94,7 @@ impl PerNs {
impl DefMap {
pub(crate) fn resolve_visibility(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
// module to import to
original_module: LocalModuleId,
@@ -101,8 +105,14 @@ impl DefMap {
) -> Option<Visibility> {
let mut vis = match visibility {
RawVisibility::Module(path, explicitness) => {
- let (result, remaining) =
- self.resolve_path(db, original_module, path, BuiltinShadowMode::Module, None);
+ let (result, remaining) = self.resolve_path(
+ local_def_map,
+ db,
+ original_module,
+ path,
+ BuiltinShadowMode::Module,
+ None,
+ );
if remaining.is_some() {
return None;
}
@@ -137,6 +147,7 @@ impl DefMap {
// the result.
pub(super) fn resolve_path_fp_with_macro(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
mode: ResolveMode,
// module to import to
@@ -148,6 +159,7 @@ impl DefMap {
expected_macro_subns: Option<MacroSubNs>,
) -> ResolvePathResult {
let mut result = self.resolve_path_fp_with_macro_single(
+ local_def_map,
db,
mode,
original_module,
@@ -196,6 +208,7 @@ impl DefMap {
current_map = &arc;
let new = current_map.resolve_path_fp_in_all_preludes(
+ local_def_map,
db,
mode,
original_module,
@@ -210,6 +223,7 @@ impl DefMap {
}
let new = current_map.resolve_path_fp_with_macro_single(
+ local_def_map,
db,
mode,
original_module,
@@ -224,6 +238,7 @@ impl DefMap {
pub(super) fn resolve_path_fp_with_macro_single(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
mode: ResolveMode,
original_module: LocalModuleId,
@@ -258,7 +273,12 @@ impl DefMap {
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
};
tracing::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
- self.resolve_name_in_crate_root_or_extern_prelude(db, original_module, segment)
+ self.resolve_name_in_crate_root_or_extern_prelude(
+ local_def_map,
+ db,
+ original_module,
+ segment,
+ )
}
PathKind::Plain => {
let (_, segment) = match segments.next() {
@@ -276,6 +296,7 @@ impl DefMap {
tracing::debug!("resolving {:?} in module", segment);
self.resolve_name_in_module(
+ local_def_map,
db,
original_module,
segment,
@@ -321,7 +342,9 @@ impl DefMap {
// with), resolve the remaining path segments in that `DefMap`.
let path =
ModPath::from_segments(PathKind::SELF, path.segments().iter().cloned());
+ // This is the same crate, so the local def map is the same.
return def_map.resolve_path_fp_with_macro(
+ local_def_map,
db,
mode,
local_id,
@@ -333,10 +356,10 @@ impl DefMap {
PerNs::types(module.into(), Visibility::Public, None)
}
- PathKind::Abs => match self.resolve_path_abs(&mut segments, path) {
+ PathKind::Abs => match self.resolve_path_abs(local_def_map, &mut segments, path) {
Either::Left(it) => it,
Either::Right(reached_fixed_point) => {
- return ResolvePathResult::empty(reached_fixed_point)
+ return ResolvePathResult::empty(reached_fixed_point);
}
},
};
@@ -347,6 +370,7 @@ impl DefMap {
/// Resolves a path only in the preludes, without accounting for item scopes.
pub(super) fn resolve_path_fp_in_all_preludes(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
mode: ResolveMode,
original_module: LocalModuleId,
@@ -368,7 +392,7 @@ impl DefMap {
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
};
tracing::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
- self.resolve_name_in_extern_prelude(segment)
+ self.resolve_name_in_extern_prelude(local_def_map, segment)
}
PathKind::Plain => {
let (_, segment) = match segments.next() {
@@ -376,16 +400,16 @@ impl DefMap {
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
};
tracing::debug!("resolving {:?} in module", segment);
- self.resolve_name_in_all_preludes(db, segment)
+ self.resolve_name_in_all_preludes(local_def_map, db, segment)
}
- PathKind::Abs => match self.resolve_path_abs(&mut segments, path) {
+ PathKind::Abs => match self.resolve_path_abs(local_def_map, &mut segments, path) {
Either::Left(it) => it,
Either::Right(reached_fixed_point) => {
- return ResolvePathResult::empty(reached_fixed_point)
+ return ResolvePathResult::empty(reached_fixed_point);
}
},
PathKind::DollarCrate(_) | PathKind::Crate | PathKind::Super(_) => {
- return ResolvePathResult::empty(ReachedFixedPoint::Yes)
+ return ResolvePathResult::empty(ReachedFixedPoint::Yes);
}
};
@@ -395,6 +419,7 @@ impl DefMap {
/// 2018-style absolute path -- only extern prelude
fn resolve_path_abs<'a>(
&self,
+ local_def_map: &LocalDefMap,
segments: &mut impl Iterator<Item = (usize, &'a Name)>,
path: &ModPath,
) -> Either<PerNs, ReachedFixedPoint> {
@@ -402,7 +427,7 @@ impl DefMap {
Some((_, segment)) => segment,
None => return Either::Right(ReachedFixedPoint::Yes),
};
- if let Some(&(def, extern_crate)) = self.data.extern_prelude.get(segment) {
+ if let Some(&(def, extern_crate)) = local_def_map.extern_prelude.get(segment) {
tracing::debug!("absolute path {:?} resolved to crate {:?}", path, def);
Either::Left(PerNs::types(
def.into(),
@@ -451,6 +476,7 @@ impl DefMap {
// this point, we know we're resolving a multi-segment path so macro kind
// expectation is discarded.
let resolution = defp_map.resolve_path_fp_with_macro(
+ LocalDefMap::EMPTY,
db,
ResolveMode::Other,
module.local_id,
@@ -483,33 +509,24 @@ impl DefMap {
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
// enum variant
cov_mark::hit!(can_import_enum_variant);
- let def_map;
- let loc = e.lookup(db);
- let tree = loc.id.item_tree(db);
- let current_def_map =
- self.krate == loc.container.krate && self.block_id() == loc.container.block;
- let res = if current_def_map {
- &self.enum_definitions[&e]
- } else {
- def_map = loc.container.def_map(db);
- &def_map.enum_definitions[&e]
- }
- .iter()
- .find_map(|&variant| {
- let variant_data = &tree[variant.lookup(db).id.value];
- (variant_data.name == *segment).then(|| match variant_data.shape {
- FieldsShape::Record => {
- PerNs::types(variant.into(), Visibility::Public, None)
- }
- FieldsShape::Tuple | FieldsShape::Unit => PerNs::both(
- variant.into(),
- variant.into(),
- Visibility::Public,
- None,
- ),
- })
- });
+ let res =
+ db.enum_variants(e).variants.iter().find(|(_, name)| name == segment).map(
+ |&(variant, _)| {
+ let item_tree_id = variant.lookup(db).id;
+ match item_tree_id.item_tree(db)[item_tree_id.value].shape {
+ FieldsShape::Record => {
+ PerNs::types(variant.into(), Visibility::Public, None)
+ }
+ FieldsShape::Tuple | FieldsShape::Unit => PerNs::both(
+ variant.into(),
+ variant.into(),
+ Visibility::Public,
+ None,
+ ),
+ }
+ },
+ );
// FIXME: Need to filter visibility here and below? Not sure.
return match res {
Some(res) => {
@@ -568,6 +585,7 @@ impl DefMap {
fn resolve_name_in_module(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
module: LocalModuleId,
name: &Name,
@@ -611,7 +629,7 @@ impl DefMap {
// they might been shadowed by local names.
return PerNs::none();
}
- self.resolve_name_in_extern_prelude(name)
+ self.resolve_name_in_extern_prelude(local_def_map, name)
};
let macro_use_prelude = || self.resolve_in_macro_use_prelude(name);
let prelude = || {
@@ -628,19 +646,24 @@ impl DefMap {
.or_else(prelude)
}
- fn resolve_name_in_all_preludes(&self, db: &dyn DefDatabase, name: &Name) -> PerNs {
+ fn resolve_name_in_all_preludes(
+ &self,
+ local_def_map: &LocalDefMap,
+ db: &dyn DefDatabase,
+ name: &Name,
+ ) -> PerNs {
// Resolve in:
// - extern prelude / macro_use prelude
// - std prelude
- let extern_prelude = self.resolve_name_in_extern_prelude(name);
+ let extern_prelude = self.resolve_name_in_extern_prelude(local_def_map, name);
let macro_use_prelude = || self.resolve_in_macro_use_prelude(name);
let prelude = || self.resolve_in_prelude(db, name);
extern_prelude.or_else(macro_use_prelude).or_else(prelude)
}
- fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
- self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| {
+ fn resolve_name_in_extern_prelude(&self, local_def_map: &LocalDefMap, name: &Name) -> PerNs {
+ local_def_map.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| {
PerNs::types(
it.into(),
Visibility::Public,
@@ -662,6 +685,7 @@ impl DefMap {
fn resolve_name_in_crate_root_or_extern_prelude(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
module: LocalModuleId,
name: &Name,
@@ -678,7 +702,7 @@ impl DefMap {
// Don't resolve extern prelude in pseudo-module of a block.
return PerNs::none();
}
- self.resolve_name_in_extern_prelude(name)
+ self.resolve_name_in_extern_prelude(local_def_map, name)
};
from_crate_root.or_else(from_extern_prelude)