Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/item_scope.rs')
-rw-r--r--crates/hir-def/src/item_scope.rs114
1 files changed, 78 insertions, 36 deletions
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index d86c0667a0..df6b1f55c1 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -1,10 +1,9 @@
//! Describes items defined or visible (ie, imported) in a certain scope.
//! This is shared between modules and blocks.
-use std::collections::hash_map::Entry;
-
use base_db::CrateId;
use hir_expand::{attrs::AttrId, db::ExpandDatabase, name::Name, AstId, MacroCallId};
+use indexmap::map::Entry;
use itertools::Itertools;
use la_arena::Idx;
use once_cell::sync::Lazy;
@@ -17,8 +16,8 @@ use crate::{
db::DefDatabase,
per_ns::PerNs,
visibility::{Visibility, VisibilityExplicitness},
- AdtId, BuiltinType, ConstId, ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId,
- ModuleDefId, ModuleId, TraitId, UseId,
+ AdtId, BuiltinType, ConstId, ExternCrateId, FxIndexMap, HasModule, ImplId, LocalModuleId,
+ Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId,
};
#[derive(Debug, Default)]
@@ -62,14 +61,26 @@ pub struct ImportId {
pub idx: Idx<ast::UseTree>,
}
+impl PerNsGlobImports {
+ pub(crate) fn contains_type(&self, module_id: LocalModuleId, name: Name) -> bool {
+ self.types.contains(&(module_id, name))
+ }
+ pub(crate) fn contains_value(&self, module_id: LocalModuleId, name: Name) -> bool {
+ self.values.contains(&(module_id, name))
+ }
+ pub(crate) fn contains_macro(&self, module_id: LocalModuleId, name: Name) -> bool {
+ self.macros.contains(&(module_id, name))
+ }
+}
+
#[derive(Debug, Default, PartialEq, Eq)]
pub struct ItemScope {
/// Defs visible in this scope. This includes `declarations`, but also
/// imports. The imports belong to this module and can be resolved by using them on
/// the `use_imports_*` fields.
- types: FxHashMap<Name, (ModuleDefId, Visibility, Option<ImportOrExternCrate>)>,
- values: FxHashMap<Name, (ModuleDefId, Visibility, Option<ImportId>)>,
- macros: FxHashMap<Name, (MacroId, Visibility, Option<ImportId>)>,
+ types: FxIndexMap<Name, (ModuleDefId, Visibility, Option<ImportOrExternCrate>)>,
+ values: FxIndexMap<Name, (ModuleDefId, Visibility, Option<ImportId>)>,
+ macros: FxIndexMap<Name, (MacroId, Visibility, Option<ImportId>)>,
unresolved: FxHashSet<Name>,
/// The defs declared in this scope. Each def has a single scope where it is
@@ -118,8 +129,8 @@ struct DeriveMacroInvocation {
derive_call_ids: SmallVec<[Option<MacroCallId>; 1]>,
}
-pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
- BuiltinType::ALL
+pub(crate) static BUILTIN_SCOPE: Lazy<FxIndexMap<Name, PerNs>> = Lazy::new(|| {
+ BuiltinType::all_builtin_types()
.iter()
.map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public, None)))
.collect()
@@ -511,38 +522,48 @@ impl ItemScope {
entry.insert(fld);
changed = true;
}
- Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => {
- if glob_imports.types.remove(&lookup) {
- let import = match import {
- Some(ImportType::ExternCrate(extern_crate)) => {
- Some(ImportOrExternCrate::ExternCrate(extern_crate))
- }
- Some(ImportType::Import(import)) => {
- Some(ImportOrExternCrate::Import(import))
- }
- None | Some(ImportType::Glob(_)) => None,
- };
- let prev = std::mem::replace(&mut fld.2, import);
- if let Some(import) = import {
- self.use_imports_types.insert(
- import,
- match prev {
- Some(ImportOrExternCrate::Import(import)) => {
- ImportOrDef::Import(import)
+ Entry::Occupied(mut entry) => {
+ match import {
+ Some(ImportType::Glob(..)) => {
+ // Multiple globs may import the same item and they may
+ // override visibility from previously resolved globs. This is
+ // currently handled by `DefCollector`, because we need to
+ // compute the max visibility for items and we need `DefMap`
+ // for that.
+ }
+ _ => {
+ if glob_imports.types.remove(&lookup) {
+ let import = match import {
+ Some(ImportType::ExternCrate(extern_crate)) => {
+ Some(ImportOrExternCrate::ExternCrate(extern_crate))
}
- Some(ImportOrExternCrate::ExternCrate(import)) => {
- ImportOrDef::ExternCrate(import)
+ Some(ImportType::Import(import)) => {
+ Some(ImportOrExternCrate::Import(import))
}
- None => ImportOrDef::Def(fld.0),
- },
- );
+ None | Some(ImportType::Glob(_)) => None,
+ };
+ let prev = std::mem::replace(&mut fld.2, import);
+ if let Some(import) = import {
+ self.use_imports_types.insert(
+ import,
+ match prev {
+ Some(ImportOrExternCrate::Import(import)) => {
+ ImportOrDef::Import(import)
+ }
+ Some(ImportOrExternCrate::ExternCrate(import)) => {
+ ImportOrDef::ExternCrate(import)
+ }
+ None => ImportOrDef::Def(fld.0),
+ },
+ );
+ }
+ cov_mark::hit!(import_shadowed);
+ entry.insert(fld);
+ changed = true;
+ }
}
- cov_mark::hit!(import_shadowed);
- entry.insert(fld);
- changed = true;
}
}
- _ => {}
}
}
@@ -757,6 +778,27 @@ impl ItemScope {
}
}
+// These methods are a temporary measure only meant to be used by `DefCollector::push_res_and_update_glob_vis()`.
+impl ItemScope {
+ pub(crate) fn update_visibility_types(&mut self, name: &Name, vis: Visibility) {
+ let res =
+ self.types.get_mut(name).expect("tried to update visibility of non-existent type");
+ res.1 = vis;
+ }
+
+ pub(crate) fn update_visibility_values(&mut self, name: &Name, vis: Visibility) {
+ let res =
+ self.values.get_mut(name).expect("tried to update visibility of non-existent value");
+ res.1 = vis;
+ }
+
+ pub(crate) fn update_visibility_macros(&mut self, name: &Name, vis: Visibility) {
+ let res =
+ self.macros.get_mut(name).expect("tried to update visibility of non-existent macro");
+ res.1 = vis;
+ }
+}
+
impl PerNs {
pub(crate) fn from_def(
def: ModuleDefId,