diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs index 601878e8e7..a389a283b5 100644 --- a/crates/hir-def/src/body/pretty.rs +++ b/crates/hir-def/src/body/pretty.rs @@ -18,27 +18,21 @@ use super::*; pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBodyId) -> String { let header = match owner { DefWithBodyId::FunctionId(it) => { - let item_tree_id = it.lookup(db).id; + it.lookup(db).id.resolved(db, |it| format!("fn {} = ", it.name.display(db.upcast()))) + } + DefWithBodyId::StaticId(it) => it + .lookup(db) + .id + .resolved(db, |it| format!("static {} = ", it.name.display(db.upcast()))), + DefWithBodyId::ConstId(it) => it.lookup(db).id.resolved(db, |it| { format!( - "fn {}", - item_tree_id.item_tree(db)[item_tree_id.value].name.display(db.upcast()) + "const {} = ", + match &it.name { + Some(name) => name.display(db.upcast()).to_string(), + None => "_".to_string(), + } ) - } - DefWithBodyId::StaticId(it) => { - let item_tree_id = it.lookup(db).id; - format!( - "static {} = ", - item_tree_id.item_tree(db)[item_tree_id.value].name.display(db.upcast()) - ) - } - DefWithBodyId::ConstId(it) => { - let item_tree_id = it.lookup(db).id; - let name = match &item_tree_id.item_tree(db)[item_tree_id.value].name { - Some(name) => name.display(db.upcast()).to_string(), - None => "_".to_string(), - }; - format!("const {name} = ") - } + }), DefWithBodyId::InTypeConstId(_) => format!("In type const = "), DefWithBodyId::VariantId(it) => { let loc = it.lookup(db); diff --git a/crates/hir-def/src/child_by_source.rs b/crates/hir-def/src/child_by_source.rs index e8a771141e..b3bb3355f1 100644 --- a/crates/hir-def/src/child_by_source.rs +++ b/crates/hir-def/src/child_by_source.rs @@ -204,15 +204,18 @@ impl ChildBySource for VariantId { } impl ChildBySource for EnumId { - fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, _: HirFileId) { + fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { let loc = &self.lookup(db); + if file_id != loc.id.file_id() { + return; + } let tree = loc.id.item_tree(db); let ast_id_map = db.ast_id_map(loc.id.file_id()); let root = db.parse_or_expand(loc.id.file_id()); db.enum_data(*self).variants.iter().for_each(|&(variant, _)| { - res[keys::VARIANT].insert( + res[keys::ENUM_VARIANT].insert( ast_id_map.get(tree[variant.lookup(db).id.value].ast_id).to_node(&root), variant, ); diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index 93a64dc6ec..942fafe329 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -298,7 +298,7 @@ impl EnumData { Arc::new(EnumData { name: enum_.name.clone(), - variants: loc.container.def_map(db)[loc.container.local_id].scope.enums[&e] + variants: loc.container.def_map(db).enum_definitions[&e] .iter() .map(|&id| (id, item_tree[id.lookup(db).id.value].name.clone())) .collect(), @@ -332,7 +332,7 @@ impl EnumVariantData { pub(crate) fn enum_variant_data_with_diagnostics_query( db: &dyn DefDatabase, e: EnumVariantId, - ) -> (Arc, Arc<[DefDiagnostic]>) { + ) -> (Arc, Option>>) { let loc = e.lookup(db); let krate = loc.container.krate; let item_tree = loc.id.item_tree(db); @@ -355,7 +355,11 @@ impl EnumVariantData { name: variant.name.clone(), variant_data: Arc::new(var_data), }), - field_diagnostics.into(), + if field_diagnostics.is_empty() { + None + } else { + Some(Arc::new(field_diagnostics.into_boxed_slice())) + }, ) } } diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index 4201b1dd17..2b1d0bca28 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -140,7 +140,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast (Arc, Arc<[DefDiagnostic]>); + ) -> (Arc, Option>>); #[salsa::invoke(ImplData::impl_data_query)] fn impl_data(&self, e: ImplId) -> Arc; diff --git a/crates/hir-def/src/dyn_map/keys.rs b/crates/hir-def/src/dyn_map/keys.rs index d0f2bfab43..60832f59eb 100644 --- a/crates/hir-def/src/dyn_map/keys.rs +++ b/crates/hir-def/src/dyn_map/keys.rs @@ -28,7 +28,7 @@ pub const ENUM: Key = Key::new(); pub const EXTERN_CRATE: Key = Key::new(); pub const USE: Key = Key::new(); -pub const VARIANT: Key = Key::new(); +pub const ENUM_VARIANT: Key = Key::new(); pub const TUPLE_FIELD: Key = Key::new(); pub const RECORD_FIELD: Key = Key::new(); pub const TYPE_PARAM: Key = Key::new(); diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 436bc0c98c..168ee4acff 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -18,8 +18,8 @@ use crate::{ db::DefDatabase, per_ns::PerNs, visibility::{Visibility, VisibilityExplicity}, - AdtId, BuiltinType, ConstId, EnumId, EnumVariantId, ExternCrateId, HasModule, ImplId, - LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, + AdtId, BuiltinType, ConstId, ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId, + ModuleDefId, ModuleId, TraitId, UseId, }; #[derive(Debug, Default)] @@ -79,7 +79,6 @@ pub struct ItemScope { /// declared. declarations: Vec, - pub enums: FxHashMap>, impls: Vec, unnamed_consts: Vec, /// Traits imported via `use Trait as _;`. @@ -719,7 +718,6 @@ impl ItemScope { use_imports_types, use_imports_macros, macro_invocations, - enums, } = self; types.shrink_to_fit(); values.shrink_to_fit(); @@ -738,7 +736,6 @@ impl ItemScope { extern_crate_decls.shrink_to_fit(); use_decls.shrink_to_fit(); macro_invocations.shrink_to_fit(); - enums.shrink_to_fit(); } } diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 0f81bef500..173aa817b0 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -445,6 +445,13 @@ impl ItemTreeId { pub fn item_tree(self, db: &dyn DefDatabase) -> Arc { self.tree.item_tree(db) } + + pub fn resolved(self, db: &dyn DefDatabase, cb: impl FnOnce(&N) -> R) -> R + where + ItemTree: Index, Output = N>, + { + cb(&self.tree.item_tree(db)[self.value]) + } } impl Copy for ItemTreeId {} diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs index fc2edce93d..bd2d804e4b 100644 --- a/crates/hir-def/src/lang_item.rs +++ b/crates/hir-def/src/lang_item.rs @@ -125,7 +125,7 @@ impl LangItems { } ModuleDefId::AdtId(AdtId::EnumId(e)) => { lang_items.collect_lang_item(db, e, LangItemTarget::EnumId); - module_data.scope.enums[&e].iter().for_each(|&id| { + crate_def_map.enum_definitions[&e].iter().for_each(|&id| { lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant); }); } diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 53644f58ef..7eb2f3addd 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -80,8 +80,8 @@ use crate::{ path::ModPath, per_ns::PerNs, visibility::{Visibility, VisibilityExplicity}, - AstId, BlockId, BlockLoc, CrateRootModuleId, ExternCrateId, FunctionId, LocalModuleId, Lookup, - MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, + AstId, BlockId, BlockLoc, CrateRootModuleId, EnumId, EnumVariantId, ExternCrateId, FunctionId, + LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, }; /// Contains the results of (early) name resolution. @@ -113,6 +113,7 @@ pub struct DefMap { /// this contains all kinds of macro, not just `macro_rules!` macro. /// ExternCrateId being None implies it being imported from the general prelude import. macro_use_prelude: FxHashMap)>, + pub(crate) enum_definitions: FxHashMap>, /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper /// attributes. @@ -370,6 +371,7 @@ impl DefMap { macro_use_prelude: FxHashMap::default(), derive_helpers_in_scope: FxHashMap::default(), diagnostics: Vec::new(), + enum_definitions: FxHashMap::default(), data: Arc::new(DefMapCrateData { extern_prelude: FxHashMap::default(), exported_derives: FxHashMap::default(), @@ -612,12 +614,14 @@ impl DefMap { krate: _, prelude: _, data: _, + enum_definitions, } = self; macro_use_prelude.shrink_to_fit(); diagnostics.shrink_to_fit(); modules.shrink_to_fit(); derive_helpers_in_scope.shrink_to_fit(); + enum_definitions.shrink_to_fit(); for (_, module) in modules.iter_mut() { module.children.shrink_to_fit(); module.scope.shrink_to_fit(); diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index fc15a77e8c..760f811ede 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -980,35 +980,26 @@ impl DefCollector<'_> { cov_mark::hit!(glob_enum); // glob import from enum => just import all the variants - // We need to check if the def map the enum is from is us, then we can't + // We need to check if the def map the enum is from is us, if it is we can't // call the def-map query since we are currently constructing it! let loc = e.lookup(self.db); let tree = loc.id.item_tree(self.db); let current_def_map = self.def_map.krate == loc.container.krate && self.def_map.block_id() == loc.container.block; + let def_map; let resolutions = if current_def_map { - self.def_map.modules[loc.container.local_id].scope.enums[&e] - .iter() - .map(|&variant| { - let name = tree[variant.lookup(self.db).id.value].name.clone(); - let res = - PerNs::both(variant.into(), variant.into(), vis, None); - (Some(name), res) - }) - .collect::>() + &self.def_map.enum_definitions[&e] } else { - loc.container.def_map(self.db).modules[loc.container.local_id] - .scope - .enums[&e] - .iter() - .map(|&variant| { - let name = tree[variant.lookup(self.db).id.value].name.clone(); - let res = - PerNs::both(variant.into(), variant.into(), vis, None); - (Some(name), res) - }) - .collect::>() - }; + def_map = loc.container.def_map(self.db); + &def_map.enum_definitions[&e] + } + .iter() + .map(|&variant| { + let name = tree[variant.lookup(self.db).id.value].name.clone(); + let res = PerNs::both(variant.into(), variant.into(), vis, None); + (Some(name), res) + }) + .collect::>(); self.update(module_id, &resolutions, vis, Some(ImportType::Glob(id))); } Some(d) => { @@ -1749,10 +1740,7 @@ impl ModCollector<'_, '_> { ) }) .collect(); - self.def_collector.def_map.modules[module_id] - .scope - .enums - .insert(enum_, variants); + self.def_collector.def_map.enum_definitions.insert(enum_, variants); } ModItem::Const(id) => { let it = &self.item_tree[id]; diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index 372d148021..7300a0628f 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -360,41 +360,28 @@ impl DefMap { let tree = loc.id.item_tree(db); let current_def_map = self.krate == loc.container.krate && self.block_id() == loc.container.block; + let def_map; let res = if current_def_map { - self.modules[loc.container.local_id].scope.enums[&e].iter().find_map( - |&variant| { - let variant_data = &tree[variant.lookup(db).id.value]; - (variant_data.name == *segment).then(|| match variant_data.fields { - Fields::Record(_) => { - PerNs::types(variant.into(), Visibility::Public, None) - } - Fields::Tuple(_) | Fields::Unit => PerNs::both( - variant.into(), - variant.into(), - Visibility::Public, - None, - ), - }) - }, - ) + &self.enum_definitions[&e] } else { - loc.container.def_map(db).modules[loc.container.local_id].scope.enums[&e] - .iter() - .find_map(|&variant| { - let variant_data = &tree[variant.lookup(db).id.value]; - (variant_data.name == *segment).then(|| match variant_data.fields { - Fields::Record(_) => { - PerNs::types(variant.into(), Visibility::Public, None) - } - Fields::Tuple(_) | Fields::Unit => PerNs::both( - variant.into(), - variant.into(), - Visibility::Public, - None, - ), - }) - }) - }; + 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.fields { + Fields::Record(_) => { + PerNs::types(variant.into(), Visibility::Public, None) + } + Fields::Tuple(_) | Fields::Unit => PerNs::both( + variant.into(), + variant.into(), + Visibility::Public, + None, + ), + }) + }); match res { Some(res) => res, None => { diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 246fc231b4..5e133bf5c7 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -584,8 +584,11 @@ impl Module { Adt::Enum(e) => { for v in e.variants(db) { acc.extend(ModuleDef::Variant(v).diagnostics(db)); - for diag in db.enum_variant_data_with_diagnostics(v.id).1.iter() { - emit_def_diagnostic(db, acc, diag); + if let Some(diags) = &db.enum_variant_data_with_diagnostics(v.id).1 + { + for diag in &***diags { + emit_def_diagnostic(db, acc, diag); + } } } } diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index df8c1e904f..cb04f98911 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -201,7 +201,7 @@ impl SourceToDefCtx<'_, '_> { &mut self, src: InFile, ) -> Option { - self.to_def(src, keys::VARIANT) + self.to_def(src, keys::ENUM_VARIANT) } pub(super) fn extern_crate_to_def( &mut self,