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.rs85
1 files changed, 53 insertions, 32 deletions
diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index de22ea1014..460a908b6d 100644
--- a/crates/hir-def/src/nameres/path_resolution.rs
+++ b/crates/hir-def/src/nameres/path_resolution.rs
@@ -15,8 +15,9 @@ use hir_expand::name::Name;
use triomphe::Arc;
use crate::{
+ data::adt::VariantData,
db::DefDatabase,
- item_scope::BUILTIN_SCOPE,
+ item_scope::{ImportOrExternCrate, BUILTIN_SCOPE},
nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs},
path::{ModPath, PathKind},
per_ns::PerNs,
@@ -65,7 +66,7 @@ impl PerNs {
db: &dyn DefDatabase,
expected: Option<MacroSubNs>,
) -> Self {
- self.macros = self.macros.filter(|&(id, _)| {
+ self.macros = self.macros.filter(|&(id, _, _)| {
let this = MacroSubNs::from_id(db, id);
sub_namespace_match(Some(this), expected)
});
@@ -196,15 +197,15 @@ impl DefMap {
PathKind::DollarCrate(krate) => {
if krate == self.krate {
cov_mark::hit!(macro_dollar_crate_self);
- PerNs::types(self.crate_root().into(), Visibility::Public)
+ PerNs::types(self.crate_root().into(), Visibility::Public, None)
} else {
let def_map = db.crate_def_map(krate);
let module = def_map.module_id(Self::ROOT);
cov_mark::hit!(macro_dollar_crate_other);
- PerNs::types(module.into(), Visibility::Public)
+ PerNs::types(module.into(), Visibility::Public, None)
}
}
- PathKind::Crate => PerNs::types(self.crate_root().into(), Visibility::Public),
+ PathKind::Crate => PerNs::types(self.crate_root().into(), Visibility::Public, None),
// plain import or absolute path in 2015: crate-relative with
// fallback to extern prelude (with the simplification in
// rust-lang/rust#57745)
@@ -291,7 +292,7 @@ impl DefMap {
);
}
- PerNs::types(module.into(), Visibility::Public)
+ PerNs::types(module.into(), Visibility::Public, None)
}
PathKind::Abs => {
// 2018-style absolute path -- only extern prelude
@@ -299,9 +300,13 @@ impl DefMap {
Some((_, segment)) => segment,
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
};
- if let Some(&def) = self.data.extern_prelude.get(segment) {
+ if let Some(&(def, extern_crate)) = self.data.extern_prelude.get(segment) {
tracing::debug!("absolute path {:?} resolved to crate {:?}", path, def);
- PerNs::types(def.into(), Visibility::Public)
+ PerNs::types(
+ def.into(),
+ Visibility::Public,
+ extern_crate.map(ImportOrExternCrate::ExternCrate),
+ )
} else {
return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
}
@@ -309,7 +314,7 @@ impl DefMap {
};
for (i, segment) in segments {
- let (curr, vis) = match curr_per_ns.take_types_vis() {
+ let (curr, vis, imp) = match curr_per_ns.take_types_full() {
Some(r) => r,
None => {
// we still have path segments left, but the path so far
@@ -364,18 +369,20 @@ impl DefMap {
Some(local_id) => {
let variant = EnumVariantId { parent: e, local_id };
match &*enum_data.variants[local_id].variant_data {
- crate::data::adt::VariantData::Record(_) => {
- PerNs::types(variant.into(), Visibility::Public)
- }
- crate::data::adt::VariantData::Tuple(_)
- | crate::data::adt::VariantData::Unit => {
- PerNs::both(variant.into(), variant.into(), Visibility::Public)
+ VariantData::Record(_) => {
+ PerNs::types(variant.into(), Visibility::Public, None)
}
+ VariantData::Tuple(_) | VariantData::Unit => PerNs::both(
+ variant.into(),
+ variant.into(),
+ Visibility::Public,
+ None,
+ ),
}
}
None => {
return ResolvePathResult::with(
- PerNs::types(e.into(), vis),
+ PerNs::types(e.into(), vis, imp),
ReachedFixedPoint::Yes,
Some(i),
Some(self.krate),
@@ -393,7 +400,7 @@ impl DefMap {
);
return ResolvePathResult::with(
- PerNs::types(s, vis),
+ PerNs::types(s, vis, imp),
ReachedFixedPoint::Yes,
Some(i),
Some(self.krate),
@@ -430,7 +437,7 @@ impl DefMap {
.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));
+ .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public, None));
let from_scope = self[module].scope.get(name).filter_macro(db, expected_macro_subns);
let from_builtin = match self.block {
Some(_) => {
@@ -449,18 +456,27 @@ impl DefMap {
let extern_prelude = || {
if self.block.is_some() {
- // Don't resolve extern prelude in block `DefMap`s.
+ // Don't resolve extern prelude in block `DefMap`s, defer it to the crate def map so
+ // that blocks can properly shadow them
return PerNs::none();
}
- self.data
- .extern_prelude
- .get(name)
- .map_or(PerNs::none(), |&it| PerNs::types(it.into(), Visibility::Public))
+ self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| {
+ PerNs::types(
+ it.into(),
+ Visibility::Public,
+ extern_crate.map(ImportOrExternCrate::ExternCrate),
+ )
+ })
};
let macro_use_prelude = || {
- self.macro_use_prelude
- .get(name)
- .map_or(PerNs::none(), |&it| PerNs::macros(it.into(), Visibility::Public))
+ self.macro_use_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| {
+ PerNs::macros(
+ it.into(),
+ Visibility::Public,
+ // FIXME?
+ None, // extern_crate.map(ImportOrExternCrate::ExternCrate),
+ )
+ })
};
let prelude = || self.resolve_in_prelude(db, name);
@@ -488,18 +504,23 @@ impl DefMap {
// Don't resolve extern prelude in block `DefMap`s.
return PerNs::none();
}
- self.data
- .extern_prelude
- .get(name)
- .copied()
- .map_or(PerNs::none(), |it| PerNs::types(it.into(), Visibility::Public))
+ self.data.extern_prelude.get(name).copied().map_or(
+ PerNs::none(),
+ |(it, extern_crate)| {
+ PerNs::types(
+ it.into(),
+ Visibility::Public,
+ extern_crate.map(ImportOrExternCrate::ExternCrate),
+ )
+ },
+ )
};
from_crate_root.or_else(from_extern_prelude)
}
fn resolve_in_prelude(&self, db: &dyn DefDatabase, name: &Name) -> PerNs {
- if let Some(prelude) = self.prelude {
+ if let Some((prelude, _use)) = self.prelude {
let keep;
let def_map = if prelude.krate == self.krate {
self