diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index 30452e34aac..8fbfcc81d28 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -24,12 +24,12 @@ use triomphe::Arc; use crate::{ db::DefDatabase, - item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeNode}, + item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeModItemNode}, lang_item::LangItem, nameres::{ModuleOrigin, ModuleSource}, src::{HasChildSource, HasSource}, - AdtId, AssocItemLoc, AttrDefId, EnumId, GenericParamId, ItemLoc, LocalEnumVariantId, - LocalFieldId, Lookup, MacroId, VariantId, + AdtId, AssocItemLoc, AttrDefId, GenericParamId, ItemLoc, LocalFieldId, Lookup, MacroId, + VariantId, }; #[derive(Default, Debug, Clone, PartialEq, Eq)] @@ -70,33 +70,6 @@ impl ops::Deref for AttrsWithOwner { impl Attrs { pub const EMPTY: Self = Self(RawAttrs::EMPTY); - pub(crate) fn variants_attrs_query( - db: &dyn DefDatabase, - e: EnumId, - ) -> Arc> { - let _p = profile::span("variants_attrs_query"); - // FIXME: There should be some proper form of mapping between item tree enum variant ids and hir enum variant ids - let mut res = ArenaMap::default(); - - let loc = e.lookup(db); - let krate = loc.container.krate; - let item_tree = loc.id.item_tree(db); - let enum_ = &item_tree[loc.id.value]; - let crate_graph = db.crate_graph(); - let cfg_options = &crate_graph[krate].cfg_options; - - let mut idx = 0; - for variant in enum_.variants.clone() { - let attrs = item_tree.attrs(db, krate, variant.into()); - if attrs.is_cfg_enabled(cfg_options) { - res.insert(Idx::from_raw(RawIdx::from(idx)), attrs); - idx += 1; - } - } - - Arc::new(res) - } - pub(crate) fn fields_attrs_query( db: &dyn DefDatabase, v: VariantId, @@ -108,29 +81,11 @@ impl Attrs { let crate_graph = db.crate_graph(); let (fields, item_tree, krate) = match v { VariantId::EnumVariantId(it) => { - let e = it.parent; - let loc = e.lookup(db); - let krate = loc.container.krate; + let loc = it.lookup(db); + let krate = loc.parent.lookup(db).container.krate; let item_tree = loc.id.item_tree(db); - let enum_ = &item_tree[loc.id.value]; - - let cfg_options = &crate_graph[krate].cfg_options; - - let Some(variant) = enum_ - .variants - .clone() - .filter(|variant| { - let attrs = item_tree.attrs(db, krate, (*variant).into()); - attrs.is_cfg_enabled(cfg_options) - }) - .zip(0u32..) - .find(|(_variant, idx)| it.local_id == Idx::from_raw(RawIdx::from(*idx))) - .map(|(variant, _idx)| variant) - else { - return Arc::new(res); - }; - - (item_tree[variant].fields.clone(), item_tree, krate) + let variant = &item_tree[loc.id.value]; + (variant.fields.clone(), item_tree, krate) } VariantId::StructId(it) => { let loc = it.lookup(db); @@ -401,10 +356,12 @@ impl AttrsWithOwner { AttrDefId::FieldId(it) => { return db.fields_attrs(it.parent)[it.local_id].clone(); } - AttrDefId::EnumVariantId(it) => { - return db.variants_attrs(it.parent)[it.local_id].clone(); - } // FIXME: DRY this up + AttrDefId::EnumVariantId(it) => { + let id = it.lookup(db).id; + let tree = id.item_tree(db); + tree.raw_attrs(id.value.into()).clone() + } AttrDefId::AdtId(it) => match it { AdtId::StructId(it) => attrs_from_item_tree_loc(db, it), AdtId::EnumId(it) => attrs_from_item_tree_loc(db, it), @@ -503,12 +460,7 @@ impl AttrsWithOwner { AdtId::EnumId(id) => any_has_attrs(db, id), }, AttrDefId::FunctionId(id) => any_has_attrs(db, id), - AttrDefId::EnumVariantId(id) => { - let map = db.variants_attrs_source_map(id.parent); - let file_id = id.parent.lookup(db).id.file_id(); - let root = db.parse_or_expand(file_id); - InFile::new(file_id, ast::AnyHasAttrs::new(map[id.local_id].to_node(&root))) - } + AttrDefId::EnumVariantId(id) => any_has_attrs(db, id), AttrDefId::StaticId(id) => any_has_attrs(db, id), AttrDefId::ConstId(id) => any_has_attrs(db, id), AttrDefId::TraitId(id) => any_has_attrs(db, id), @@ -654,13 +606,16 @@ fn any_has_attrs<'db>( id.lookup(db).source(db).map(ast::AnyHasAttrs::new) } -fn attrs_from_item_tree(db: &dyn DefDatabase, id: ItemTreeId) -> RawAttrs { +fn attrs_from_item_tree( + db: &dyn DefDatabase, + id: ItemTreeId, +) -> RawAttrs { let tree = id.item_tree(db); let mod_item = N::id_to_mod_item(id.value); tree.raw_attrs(mod_item.into()).clone() } -fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>( +fn attrs_from_item_tree_loc<'db, N: ItemTreeModItemNode>( db: &(dyn DefDatabase + 'db), lookup: impl Lookup = dyn DefDatabase + 'db, Data = ItemLoc>, ) -> RawAttrs { @@ -668,7 +623,7 @@ fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>( attrs_from_item_tree(db, id) } -fn attrs_from_item_tree_assoc<'db, N: ItemTreeNode>( +fn attrs_from_item_tree_assoc<'db, N: ItemTreeModItemNode>( db: &(dyn DefDatabase + 'db), lookup: impl Lookup = dyn DefDatabase + 'db, Data = AssocItemLoc>, ) -> RawAttrs { @@ -676,20 +631,6 @@ fn attrs_from_item_tree_assoc<'db, N: ItemTreeNode>( attrs_from_item_tree(db, id) } -pub(crate) fn variants_attrs_source_map( - db: &dyn DefDatabase, - def: EnumId, -) -> Arc>> { - let mut res = ArenaMap::default(); - let child_source = def.child_source(db); - - for (idx, variant) in child_source.value.iter() { - res.insert(idx, AstPtr::new(variant)); - } - - Arc::new(res) -} - pub(crate) fn fields_attrs_source_map( db: &dyn DefDatabase, def: VariantId, diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index 415800b9b79..36d810bbe8a 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -26,7 +26,7 @@ use crate::{ }, nameres::DefMap, path::{ModPath, Path}, - src::{HasChildSource, HasSource}, + src::HasSource, BlockId, DefWithBodyId, HasModule, Lookup, }; @@ -160,8 +160,9 @@ impl Body { src.map(|it| it.body()) } DefWithBodyId::VariantId(v) => { - let src = v.parent.child_source(db); - src.map(|it| it[v.local_id].expr()) + let s = v.lookup(db); + let src = s.source(db); + src.map(|it| it.expr()) } DefWithBodyId::InTypeConstId(c) => c.lookup(db).id.map(|_| c.source(db).expr()), } diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs index bf887e680f2..0f2b279670c 100644 --- a/crates/hir-def/src/body/pretty.rs +++ b/crates/hir-def/src/body/pretty.rs @@ -3,7 +3,6 @@ use std::fmt::{self, Write}; use itertools::Itertools; -use syntax::ast::HasName; use crate::{ hir::{ @@ -19,35 +18,30 @@ 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 src = it.parent.child_source(db); - let variant = &src.value[it.local_id]; - match &variant.name() { - Some(name) => name.to_string(), - None => "_".to_string(), - } + let loc = it.lookup(db); + let enum_loc = loc.parent.lookup(db); + format!( + "enum {}::{}", + enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast()), + loc.id.item_tree(db)[loc.id.value].name.display(db.upcast()), + ) } }; diff --git a/crates/hir-def/src/child_by_source.rs b/crates/hir-def/src/child_by_source.rs index 32c53cb9503..b3bb3355f12 100644 --- a/crates/hir-def/src/child_by_source.rs +++ b/crates/hir-def/src/child_by_source.rs @@ -13,8 +13,8 @@ use crate::{ item_scope::ItemScope, nameres::DefMap, src::{HasChildSource, HasSource}, - AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FieldId, ImplId, - Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, VariantId, + AdtId, AssocItemId, DefWithBodyId, EnumId, ExternCrateId, FieldId, ImplId, Lookup, MacroId, + ModuleDefId, ModuleId, TraitId, UseId, VariantId, }; pub trait ChildBySource { @@ -204,13 +204,22 @@ impl ChildBySource for VariantId { } impl ChildBySource for EnumId { - fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, _: HirFileId) { - let arena_map = self.child_source(db); - let arena_map = arena_map.as_ref(); - for (local_id, source) in arena_map.value.iter() { - let id = EnumVariantId { parent: *self, local_id }; - res[keys::VARIANT].insert(source.clone(), id) + 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::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.rs b/crates/hir-def/src/data.rs index 9c183c9332b..a42d6bb3378 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -19,7 +19,7 @@ use crate::{ macro_call_as_call_id, nameres::{ attr_resolution::ResolvedAttr, - diagnostics::DefDiagnostic, + diagnostics::{DefDiagnostic, DefDiagnostics}, proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind}, DefMap, MacroSubNs, }, @@ -240,7 +240,7 @@ impl TraitData { pub(crate) fn trait_data_with_diagnostics_query( db: &dyn DefDatabase, tr: TraitId, - ) -> (Arc, Arc<[DefDiagnostic]>) { + ) -> (Arc, DefDiagnostics) { let tr_loc @ ItemLoc { container: module_id, id: tree_id } = tr.lookup(db); let item_tree = tree_id.item_tree(db); let tr_def = &item_tree[tree_id.value]; @@ -274,7 +274,7 @@ impl TraitData { rustc_has_incoherent_inherent_impls, fundamental, }), - diagnostics.into(), + DefDiagnostics::new(diagnostics), ) } @@ -340,7 +340,7 @@ impl ImplData { pub(crate) fn impl_data_with_diagnostics_query( db: &dyn DefDatabase, id: ImplId, - ) -> (Arc, Arc<[DefDiagnostic]>) { + ) -> (Arc, DefDiagnostics) { let _p = profile::span("impl_data_with_diagnostics_query"); let ItemLoc { container: module_id, id: tree_id } = id.lookup(db); @@ -367,7 +367,7 @@ impl ImplData { is_unsafe, attribute_calls, }), - diagnostics.into(), + DefDiagnostics::new(diagnostics), ) } diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index 8772c34f02f..5d443715213 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -21,15 +21,14 @@ use crate::{ item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId}, lang_item::LangItem, lower::LowerCtx, - nameres::diagnostics::DefDiagnostic, + nameres::diagnostics::{DefDiagnostic, DefDiagnostics}, src::HasChildSource, src::HasSource, trace::Trace, tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree}, type_ref::TypeRef, visibility::RawVisibility, - EnumId, EnumLoc, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StructId, - UnionId, VariantId, + EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId, }; /// Note that we use `StructData` for unions as well! @@ -43,7 +42,7 @@ pub struct StructData { } bitflags! { -#[derive(Debug, Clone, PartialEq, Eq)] + #[derive(Debug, Clone, PartialEq, Eq)] pub struct StructFlags: u8 { const NO_FLAGS = 0; /// Indicates whether the struct is `PhantomData`. @@ -65,7 +64,7 @@ bitflags! { #[derive(Debug, Clone, PartialEq, Eq)] pub struct EnumData { pub name: Name, - pub variants: Arena, + pub variants: Box<[(EnumVariantId, Name)]>, pub repr: Option, pub visibility: RawVisibility, pub rustc_has_incoherent_inherent_impls: bool, @@ -75,7 +74,6 @@ pub struct EnumData { pub struct EnumVariantData { pub name: Name, pub variant_data: Arc, - pub tree_id: la_arena::Idx, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -189,7 +187,7 @@ impl StructData { pub(crate) fn struct_data_with_diagnostics_query( db: &dyn DefDatabase, id: StructId, - ) -> (Arc, Arc<[DefDiagnostic]>) { + ) -> (Arc, DefDiagnostics) { let loc = id.lookup(db); let krate = loc.container.krate; let item_tree = loc.id.item_tree(db); @@ -234,7 +232,7 @@ impl StructData { visibility: item_tree[strukt.visibility].clone(), flags, }), - diagnostics.into(), + DefDiagnostics::new(diagnostics), ) } @@ -245,7 +243,7 @@ impl StructData { pub(crate) fn union_data_with_diagnostics_query( db: &dyn DefDatabase, id: UnionId, - ) -> (Arc, Arc<[DefDiagnostic]>) { + ) -> (Arc, DefDiagnostics) { let loc = id.lookup(db); let krate = loc.container.krate; let item_tree = loc.id.item_tree(db); @@ -280,24 +278,16 @@ impl StructData { visibility: item_tree[union.visibility].clone(), flags, }), - diagnostics.into(), + DefDiagnostics::new(diagnostics), ) } } impl EnumData { pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc { - db.enum_data_with_diagnostics(e).0 - } - - pub(crate) fn enum_data_with_diagnostics_query( - db: &dyn DefDatabase, - e: EnumId, - ) -> (Arc, Arc<[DefDiagnostic]>) { let loc = e.lookup(db); let krate = loc.container.krate; let item_tree = loc.id.item_tree(db); - let cfg_options = db.crate_graph()[krate].cfg_options.clone(); let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); let rustc_has_incoherent_inherent_impls = item_tree .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()) @@ -305,53 +295,21 @@ impl EnumData { .exists(); let enum_ = &item_tree[loc.id.value]; - let mut variants = Arena::new(); - let mut diagnostics = Vec::new(); - for tree_id in enum_.variants.clone() { - let attrs = item_tree.attrs(db, krate, tree_id.into()); - let var = &item_tree[tree_id]; - if attrs.is_cfg_enabled(&cfg_options) { - let (var_data, field_diagnostics) = lower_fields( - db, - krate, - loc.id.file_id(), - loc.container.local_id, - &item_tree, - &cfg_options, - &var.fields, - Some(enum_.visibility), - ); - diagnostics.extend(field_diagnostics); - variants.alloc(EnumVariantData { - name: var.name.clone(), - variant_data: Arc::new(var_data), - tree_id, - }); - } else { - diagnostics.push(DefDiagnostic::unconfigured_code( - loc.container.local_id, - InFile::new(loc.id.file_id(), var.ast_id.erase()), - attrs.cfg().unwrap(), - cfg_options.clone(), - )) - } - } - - ( - Arc::new(EnumData { - name: enum_.name.clone(), - variants, - repr, - visibility: item_tree[enum_.visibility].clone(), - rustc_has_incoherent_inherent_impls, - }), - diagnostics.into(), - ) + Arc::new(EnumData { + name: enum_.name.clone(), + variants: loc.container.def_map(db).enum_definitions[&e] + .iter() + .map(|&id| (id, item_tree[id.lookup(db).id.value].name.clone())) + .collect(), + repr, + visibility: item_tree[enum_.visibility].clone(), + rustc_has_incoherent_inherent_impls, + }) } - pub fn variant(&self, name: &Name) -> Option { - let (id, _) = self.variants.iter().find(|(_id, data)| &data.name == name)?; + pub fn variant(&self, name: &Name) -> Option { + let &(id, _) = self.variants.iter().find(|(_id, n)| n == name)?; Some(id) } @@ -363,82 +321,47 @@ impl EnumData { } } -impl HasChildSource for EnumId { - type Value = ast::Variant; - fn child_source( - &self, +impl EnumVariantData { + pub(crate) fn enum_variant_data_query( db: &dyn DefDatabase, - ) -> InFile> { - let loc = &self.lookup(db); - let src = loc.source(db); - let mut trace = Trace::new_for_map(); - lower_enum(db, &mut trace, &src, loc); - src.with_value(trace.into_map()) + e: EnumVariantId, + ) -> Arc { + db.enum_variant_data_with_diagnostics(e).0 } -} -fn lower_enum( - db: &dyn DefDatabase, - trace: &mut Trace, - ast: &InFile, - loc: &EnumLoc, -) { - let item_tree = loc.id.item_tree(db); - let krate = loc.container.krate; + pub(crate) fn enum_variant_data_with_diagnostics_query( + db: &dyn DefDatabase, + e: EnumVariantId, + ) -> (Arc, DefDiagnostics) { + let loc = e.lookup(db); + let container = loc.parent.lookup(db).container; + let krate = container.krate; + let item_tree = loc.id.item_tree(db); + let cfg_options = db.crate_graph()[krate].cfg_options.clone(); + let variant = &item_tree[loc.id.value]; - let item_tree_variants = item_tree[loc.id.value].variants.clone(); - - let cfg_options = &db.crate_graph()[krate].cfg_options; - let variants = ast - .value - .variant_list() - .into_iter() - .flat_map(|it| it.variants()) - .zip(item_tree_variants) - .filter(|&(_, item_tree_id)| { - item_tree.attrs(db, krate, item_tree_id.into()).is_cfg_enabled(cfg_options) - }); - for (var, item_tree_id) in variants { - trace.alloc( - || var.clone(), - || EnumVariantData { - name: var.name().map_or_else(Name::missing, |it| it.as_name()), - variant_data: Arc::new(VariantData::new( - db, - ast.with_value(var.kind()), - loc.container, - &item_tree, - item_tree_id, - )), - tree_id: item_tree_id, - }, + let (var_data, diagnostics) = lower_fields( + db, + krate, + loc.id.file_id(), + container.local_id, + &item_tree, + &cfg_options, + &variant.fields, + Some(item_tree[loc.parent.lookup(db).id.value].visibility), ); + + ( + Arc::new(EnumVariantData { + name: variant.name.clone(), + variant_data: Arc::new(var_data), + }), + DefDiagnostics::new(diagnostics), + ) } } impl VariantData { - fn new( - db: &dyn DefDatabase, - flavor: InFile, - module_id: ModuleId, - item_tree: &ItemTree, - variant: la_arena::Idx, - ) -> Self { - let mut trace = Trace::new_for_arena(); - match lower_struct( - db, - &mut trace, - &flavor, - module_id.krate, - item_tree, - &item_tree[variant].fields, - ) { - StructKind::Tuple => VariantData::Tuple(trace.into_arena()), - StructKind::Record => VariantData::Record(trace.into_arena()), - StructKind::Unit => VariantData::Unit, - } - } - pub fn fields(&self) -> &Arena { const EMPTY: &Arena = &Arena::new(); match &self { @@ -468,14 +391,13 @@ impl HasChildSource for VariantId { let item_tree; let (src, fields, container) = match *self { VariantId::EnumVariantId(it) => { - // I don't really like the fact that we call into parent source - // here, this might add to more queries then necessary. - let lookup = it.parent.lookup(db); + let lookup = it.lookup(db); item_tree = lookup.id.item_tree(db); - let src = it.parent.child_source(db); - let tree_id = db.enum_data(it.parent).variants[it.local_id].tree_id; - let fields = &item_tree[tree_id].fields; - (src.map(|map| map[it.local_id].kind()), fields, lookup.container) + ( + lookup.source(db).map(|it| it.kind()), + &item_tree[lookup.id.value].fields, + lookup.parent.lookup(db).container, + ) } VariantId::StructId(it) => { let lookup = it.lookup(db); @@ -490,11 +412,7 @@ impl HasChildSource for VariantId { let lookup = it.lookup(db); item_tree = lookup.id.item_tree(db); ( - lookup.source(db).map(|it| { - it.record_field_list() - .map(ast::StructKind::Record) - .unwrap_or(ast::StructKind::Unit) - }), + lookup.source(db).map(|it| it.kind()), &item_tree[lookup.id.value].fields, lookup.container, ) diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index 70c0d5193d4..186a8cf2d9f 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -11,7 +11,7 @@ use crate::{ attr::{Attrs, AttrsWithOwner}, body::{scope::ExprScopes, Body, BodySourceMap}, data::{ - adt::{EnumData, StructData}, + adt::{EnumData, EnumVariantData, StructData}, ConstData, ExternCrateDeclData, FunctionData, ImplData, Macro2Data, MacroRulesData, ProcMacroData, StaticData, TraitAliasData, TraitData, TypeAliasData, }, @@ -19,15 +19,15 @@ use crate::{ import_map::ImportMap, item_tree::{AttrOwner, ItemTree}, lang_item::{self, LangItem, LangItemTarget, LangItems}, - nameres::{diagnostics::DefDiagnostic, DefMap}, + nameres::{diagnostics::DefDiagnostics, DefMap}, visibility::{self, Visibility}, AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId, - EnumId, EnumLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, - FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId, InTypeConstLoc, LocalEnumVariantId, - LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, - ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, - TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, - VariantId, + EnumId, EnumLoc, EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, + ExternCrateLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId, + InTypeConstLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc, + MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, + TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, + UseId, UseLoc, VariantId, }; #[salsa::query_group(InternDatabaseStorage)] @@ -46,6 +46,8 @@ pub trait InternDatabase: SourceDatabase { #[salsa::interned] fn intern_enum(&self, loc: EnumLoc) -> EnumId; #[salsa::interned] + fn intern_enum_variant(&self, loc: EnumVariantLoc) -> EnumVariantId; + #[salsa::interned] fn intern_const(&self, loc: ConstLoc) -> ConstId; #[salsa::interned] fn intern_static(&self, loc: StaticLoc) -> StaticId; @@ -119,32 +121,37 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Arc; #[salsa::invoke(StructData::struct_data_with_diagnostics_query)] - fn struct_data_with_diagnostics(&self, id: StructId) - -> (Arc, Arc<[DefDiagnostic]>); + fn struct_data_with_diagnostics(&self, id: StructId) -> (Arc, DefDiagnostics); #[salsa::invoke(StructData::union_data_query)] fn union_data(&self, id: UnionId) -> Arc; #[salsa::invoke(StructData::union_data_with_diagnostics_query)] - fn union_data_with_diagnostics(&self, id: UnionId) -> (Arc, Arc<[DefDiagnostic]>); + fn union_data_with_diagnostics(&self, id: UnionId) -> (Arc, DefDiagnostics); #[salsa::invoke(EnumData::enum_data_query)] fn enum_data(&self, e: EnumId) -> Arc; - #[salsa::invoke(EnumData::enum_data_with_diagnostics_query)] - fn enum_data_with_diagnostics(&self, e: EnumId) -> (Arc, Arc<[DefDiagnostic]>); + #[salsa::invoke(EnumVariantData::enum_variant_data_query)] + fn enum_variant_data(&self, id: EnumVariantId) -> Arc; + + #[salsa::invoke(EnumVariantData::enum_variant_data_with_diagnostics_query)] + fn enum_variant_data_with_diagnostics( + &self, + id: EnumVariantId, + ) -> (Arc, DefDiagnostics); #[salsa::invoke(ImplData::impl_data_query)] fn impl_data(&self, e: ImplId) -> Arc; #[salsa::invoke(ImplData::impl_data_with_diagnostics_query)] - fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc, Arc<[DefDiagnostic]>); + fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc, DefDiagnostics); #[salsa::invoke(TraitData::trait_data_query)] fn trait_data(&self, e: TraitId) -> Arc; #[salsa::invoke(TraitData::trait_data_with_diagnostics_query)] - fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc, Arc<[DefDiagnostic]>); + fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc, DefDiagnostics); #[salsa::invoke(TraitAliasData::trait_alias_query)] fn trait_alias_data(&self, e: TraitAliasId) -> Arc; @@ -189,18 +196,9 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Arc>; - #[salsa::invoke(Attrs::fields_attrs_query)] fn fields_attrs(&self, def: VariantId) -> Arc>; - #[salsa::invoke(crate::attr::variants_attrs_source_map)] - fn variants_attrs_source_map( - &self, - def: EnumId, - ) -> Arc>>; - #[salsa::invoke(crate::attr::fields_attrs_source_map)] fn fields_attrs_source_map( &self, diff --git a/crates/hir-def/src/dyn_map/keys.rs b/crates/hir-def/src/dyn_map/keys.rs index d0f2bfab432..60832f59eb9 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/find_path.rs b/crates/hir-def/src/find_path.rs index 67e43f15cd3..3ff51b9845c 100644 --- a/crates/hir-def/src/find_path.rs +++ b/crates/hir-def/src/find_path.rs @@ -2,7 +2,10 @@ use std::{cmp::Ordering, iter}; -use hir_expand::name::{known, AsName, Name}; +use hir_expand::{ + name::{known, AsName, Name}, + Lookup, +}; use rustc_hash::FxHashSet; use crate::{ @@ -139,9 +142,10 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() { // - if the item is an enum variant, refer to it via the enum - if let Some(mut path) = find_path_inner(ctx, ItemInNs::Types(variant.parent.into()), from) { - let data = ctx.db.enum_data(variant.parent); - path.push_segment(data.variants[variant.local_id].name.clone()); + if let Some(mut path) = + find_path_inner(ctx, ItemInNs::Types(variant.lookup(ctx.db).parent.into()), from) + { + path.push_segment(ctx.db.enum_variant_data(variant).name.clone()); return Some(path); } // If this doesn't work, it seems we have no way of referring to the diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 82ea5ffeba1..c37cf521551 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -41,7 +41,7 @@ mod tests; use std::{ fmt::{self, Debug}, hash::{Hash, Hasher}, - ops::Index, + ops::{Index, Range}, }; use ast::{AstNode, HasName, StructKind}; @@ -308,7 +308,7 @@ pub enum AttrOwner { /// Inner attributes of the source file. TopLevel, - Variant(Idx), + Variant(FileItemTreeId), Field(Idx), Param(Idx), TypeOrConstParamData(Idx), @@ -329,7 +329,7 @@ macro_rules! from_attrs { from_attrs!( ModItem(ModItem), - Variant(Idx), + Variant(FileItemTreeId), Field(Idx), Param(Idx), TypeOrConstParamData(Idx), @@ -337,7 +337,7 @@ from_attrs!( ); /// Trait implemented by all item nodes in the item tree. -pub trait ItemTreeNode: Clone { +pub trait ItemTreeModItemNode: Clone { type Source: AstIdNode + Into; fn ast_id(&self) -> FileAstId; @@ -352,35 +352,44 @@ pub trait ItemTreeNode: Clone { fn id_to_mod_item(id: FileItemTreeId) -> ModItem; } -pub struct FileItemTreeId(Idx); +pub struct FileItemTreeId(Idx); -impl FileItemTreeId { +impl FileItemTreeId { + pub fn range_iter(range: Range) -> impl Iterator { + (range.start.index().into_raw().into_u32()..range.end.index().into_raw().into_u32()) + .map(RawIdx::from_u32) + .map(Idx::from_raw) + .map(Self) + } +} + +impl FileItemTreeId { pub fn index(&self) -> Idx { self.0 } } -impl Clone for FileItemTreeId { +impl Clone for FileItemTreeId { fn clone(&self) -> Self { Self(self.0) } } -impl Copy for FileItemTreeId {} +impl Copy for FileItemTreeId {} -impl PartialEq for FileItemTreeId { +impl PartialEq for FileItemTreeId { fn eq(&self, other: &FileItemTreeId) -> bool { self.0 == other.0 } } -impl Eq for FileItemTreeId {} +impl Eq for FileItemTreeId {} -impl Hash for FileItemTreeId { +impl Hash for FileItemTreeId { fn hash(&self, state: &mut H) { self.0.hash(state) } } -impl fmt::Debug for FileItemTreeId { +impl fmt::Debug for FileItemTreeId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } @@ -415,12 +424,12 @@ impl TreeId { } #[derive(Debug)] -pub struct ItemTreeId { +pub struct ItemTreeId { tree: TreeId, pub value: FileItemTreeId, } -impl ItemTreeId { +impl ItemTreeId { pub fn new(tree: TreeId, idx: FileItemTreeId) -> Self { Self { tree, value: idx } } @@ -436,24 +445,31 @@ 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 {} -impl Clone for ItemTreeId { +impl Copy for ItemTreeId {} +impl Clone for ItemTreeId { fn clone(&self) -> Self { *self } } -impl PartialEq for ItemTreeId { +impl PartialEq for ItemTreeId { fn eq(&self, other: &Self) -> bool { self.tree == other.tree && self.value == other.value } } -impl Eq for ItemTreeId {} +impl Eq for ItemTreeId {} -impl Hash for ItemTreeId { +impl Hash for ItemTreeId { fn hash(&self, state: &mut H) { self.tree.hash(state); self.value.hash(state); @@ -478,7 +494,7 @@ macro_rules! mod_items { )+ $( - impl ItemTreeNode for $typ { + impl ItemTreeModItemNode for $typ { type Source = $ast; fn ast_id(&self) -> FileAstId { @@ -561,13 +577,20 @@ impl Index for ItemTree { } } -impl Index> for ItemTree { +impl Index> for ItemTree { type Output = N; fn index(&self, id: FileItemTreeId) -> &N { N::lookup(self, id.index()) } } +impl Index> for ItemTree { + type Output = Variant; + fn index(&self, id: FileItemTreeId) -> &Variant { + &self[id.index()] + } +} + #[derive(Debug, Clone, Eq, PartialEq)] pub struct Use { pub visibility: RawVisibilityId, @@ -678,7 +701,7 @@ pub struct Enum { pub name: Name, pub visibility: RawVisibilityId, pub generic_params: Interned, - pub variants: IdxRange, + pub variants: Range>, pub ast_id: FileAstId, } diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index 6343b43a016..f6086ed6d9b 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -13,7 +13,7 @@ use crate::{ use super::*; -fn id(index: Idx) -> FileItemTreeId { +fn id(index: Idx) -> FileItemTreeId { FileItemTreeId(index) } @@ -253,25 +253,27 @@ impl<'a> Ctx<'a> { let generic_params = self.lower_generic_params(HasImplicitSelf::No, enum_); let variants = match &enum_.variant_list() { Some(variant_list) => self.lower_variants(variant_list), - None => IdxRange::new(self.next_variant_idx()..self.next_variant_idx()), + None => { + FileItemTreeId(self.next_variant_idx())..FileItemTreeId(self.next_variant_idx()) + } }; let res = Enum { name, visibility, generic_params, variants, ast_id }; Some(id(self.data().enums.alloc(res))) } - fn lower_variants(&mut self, variants: &ast::VariantList) -> IdxRange { + fn lower_variants(&mut self, variants: &ast::VariantList) -> Range> { let start = self.next_variant_idx(); for variant in variants.variants() { if let Some(data) = self.lower_variant(&variant) { let idx = self.data().variants.alloc(data); self.add_attrs( - idx.into(), + FileItemTreeId(idx).into(), RawAttrs::new(self.db.upcast(), &variant, self.span_map()), ); } } let end = self.next_variant_idx(); - IdxRange::new(start..end) + FileItemTreeId(start)..FileItemTreeId(end) } fn lower_variant(&mut self, variant: &ast::Variant) -> Option { diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs index 8693b9a98c9..d8a0cb56983 100644 --- a/crates/hir-def/src/item_tree/pretty.rs +++ b/crates/hir-def/src/item_tree/pretty.rs @@ -318,7 +318,7 @@ impl Printer<'_> { self.print_generic_params(generic_params); self.print_where_clause_and_opening_brace(generic_params); self.indented(|this| { - for variant in variants.clone() { + for variant in FileItemTreeId::range_iter(variants.clone()) { let Variant { name, fields, ast_id: _ } = &this.tree[variant]; this.print_attrs_of(variant, "\n"); w!(this, "{}", name.display(self.db.upcast())); diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs index 1a3f53c383b..45ba939b8cf 100644 --- a/crates/hir-def/src/lang_item.rs +++ b/crates/hir-def/src/lang_item.rs @@ -125,12 +125,8 @@ impl LangItems { } ModuleDefId::AdtId(AdtId::EnumId(e)) => { lang_items.collect_lang_item(db, e, LangItemTarget::EnumId); - db.enum_data(e).variants.iter().for_each(|(local_id, _)| { - lang_items.collect_lang_item( - db, - EnumVariantId { parent: e, local_id }, - LangItemTarget::EnumVariant, - ); + crate_def_map.enum_definitions[&e].iter().for_each(|&id| { + lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant); }); } ModuleDefId::AdtId(AdtId::StructId(s)) => { diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index aa84ccaee6e..bcd1f37bec4 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -99,8 +99,8 @@ use crate::{ data::adt::VariantData, db::DefDatabase, item_tree::{ - Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules, - Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, + Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeModItemNode, Macro2, + MacroRules, Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant, }, }; @@ -213,28 +213,28 @@ impl ModuleId { pub type LocalModuleId = Idx; #[derive(Debug)] -pub struct ItemLoc { +pub struct ItemLoc { pub container: ModuleId, pub id: ItemTreeId, } -impl Clone for ItemLoc { +impl Clone for ItemLoc { fn clone(&self) -> Self { Self { container: self.container, id: self.id } } } -impl Copy for ItemLoc {} +impl Copy for ItemLoc {} -impl PartialEq for ItemLoc { +impl PartialEq for ItemLoc { fn eq(&self, other: &Self) -> bool { self.container == other.container && self.id == other.id } } -impl Eq for ItemLoc {} +impl Eq for ItemLoc {} -impl Hash for ItemLoc { +impl Hash for ItemLoc { fn hash(&self, state: &mut H) { self.container.hash(state); self.id.hash(state); @@ -242,28 +242,28 @@ impl Hash for ItemLoc { } #[derive(Debug)] -pub struct AssocItemLoc { +pub struct AssocItemLoc { pub container: ItemContainerId, pub id: ItemTreeId, } -impl Clone for AssocItemLoc { +impl Clone for AssocItemLoc { fn clone(&self) -> Self { Self { container: self.container, id: self.id } } } -impl Copy for AssocItemLoc {} +impl Copy for AssocItemLoc {} -impl PartialEq for AssocItemLoc { +impl PartialEq for AssocItemLoc { fn eq(&self, other: &Self) -> bool { self.container == other.container && self.id == other.id } } -impl Eq for AssocItemLoc {} +impl Eq for AssocItemLoc {} -impl Hash for AssocItemLoc { +impl Hash for AssocItemLoc { fn hash(&self, state: &mut H) { self.container.hash(state); self.id.hash(state); @@ -297,14 +297,16 @@ pub struct EnumId(salsa::InternId); pub type EnumLoc = ItemLoc; impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum); -// FIXME: rename to `VariantId`, only enums can ave variants #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct EnumVariantId { - pub parent: EnumId, - pub local_id: LocalEnumVariantId, -} +pub struct EnumVariantId(salsa::InternId); -pub type LocalEnumVariantId = Idx; +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct EnumVariantLoc { + pub id: ItemTreeId, + pub parent: EnumId, + pub index: u32, +} +impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_enum_variant); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct FieldId { @@ -953,23 +955,21 @@ impl VariantId { match self { VariantId::StructId(it) => db.struct_data(it).variant_data.clone(), VariantId::UnionId(it) => db.union_data(it).variant_data.clone(), - VariantId::EnumVariantId(it) => { - db.enum_data(it.parent).variants[it.local_id].variant_data.clone() - } + VariantId::EnumVariantId(it) => db.enum_variant_data(it).variant_data.clone(), } } pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId { match self { - VariantId::EnumVariantId(it) => it.parent.lookup(db).id.file_id(), + VariantId::EnumVariantId(it) => it.lookup(db).id.file_id(), VariantId::StructId(it) => it.lookup(db).id.file_id(), VariantId::UnionId(it) => it.lookup(db).id.file_id(), } } - pub fn adt_id(self) -> AdtId { + pub fn adt_id(self, db: &dyn DefDatabase) -> AdtId { match self { - VariantId::EnumVariantId(it) => it.parent.into(), + VariantId::EnumVariantId(it) => it.lookup(db).parent.into(), VariantId::StructId(it) => it.into(), VariantId::UnionId(it) => it.into(), } @@ -991,7 +991,8 @@ impl HasModule for ItemContainerId { } } -impl HasModule for AssocItemLoc { +impl HasModule for AssocItemLoc { + #[inline] fn module(&self, db: &dyn DefDatabase) -> ModuleId { self.container.module(db) } @@ -1007,7 +1008,22 @@ impl HasModule for AdtId { } } +impl HasModule for EnumId { + #[inline] + fn module(&self, db: &dyn DefDatabase) -> ModuleId { + self.lookup(db).container + } +} + +impl HasModule for EnumVariantId { + #[inline] + fn module(&self, db: &dyn DefDatabase) -> ModuleId { + self.lookup(db).parent.module(db) + } +} + impl HasModule for ExternCrateId { + #[inline] fn module(&self, db: &dyn DefDatabase) -> ModuleId { self.lookup(db).container } @@ -1016,7 +1032,7 @@ impl HasModule for ExternCrateId { impl HasModule for VariantId { fn module(&self, db: &dyn DefDatabase) -> ModuleId { match self { - VariantId::EnumVariantId(it) => it.parent.lookup(db).container, + VariantId::EnumVariantId(it) => it.lookup(db).parent.module(db), VariantId::StructId(it) => it.lookup(db).container, VariantId::UnionId(it) => it.lookup(db).container, } @@ -1045,7 +1061,7 @@ impl HasModule for TypeOwnerId { TypeOwnerId::TraitAliasId(it) => it.lookup(db).container, TypeOwnerId::TypeAliasId(it) => it.lookup(db).module(db), TypeOwnerId::ImplId(it) => it.lookup(db).container, - TypeOwnerId::EnumVariantId(it) => it.parent.lookup(db).container, + TypeOwnerId::EnumVariantId(it) => it.lookup(db).parent.module(db), } } } @@ -1056,7 +1072,7 @@ impl HasModule for DefWithBodyId { DefWithBodyId::FunctionId(it) => it.lookup(db).module(db), DefWithBodyId::StaticId(it) => it.lookup(db).module(db), DefWithBodyId::ConstId(it) => it.lookup(db).module(db), - DefWithBodyId::VariantId(it) => it.parent.lookup(db).container, + DefWithBodyId::VariantId(it) => it.lookup(db).parent.module(db), DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db), } } @@ -1071,19 +1087,21 @@ impl HasModule for GenericDefId { GenericDefId::TraitAliasId(it) => it.lookup(db).container, GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), GenericDefId::ImplId(it) => it.lookup(db).container, - GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container, + GenericDefId::EnumVariantId(it) => it.lookup(db).parent.lookup(db).container, GenericDefId::ConstId(it) => it.lookup(db).module(db), } } } impl HasModule for TypeAliasId { + #[inline] fn module(&self, db: &dyn DefDatabase) -> ModuleId { self.lookup(db).module(db) } } impl HasModule for TraitId { + #[inline] fn module(&self, db: &dyn DefDatabase) -> ModuleId { self.lookup(db).container } @@ -1098,7 +1116,7 @@ impl ModuleDefId { ModuleDefId::ModuleId(id) => *id, ModuleDefId::FunctionId(id) => id.lookup(db).module(db), ModuleDefId::AdtId(id) => id.module(db), - ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container, + ModuleDefId::EnumVariantId(id) => id.lookup(db).parent.module(db), ModuleDefId::ConstId(id) => id.lookup(db).container.module(db), ModuleDefId::StaticId(id) => id.lookup(db).module(db), ModuleDefId::TraitId(id) => id.lookup(db).container, @@ -1117,7 +1135,7 @@ impl AttrDefId { AttrDefId::FieldId(it) => it.parent.module(db).krate, AttrDefId::AdtId(it) => it.module(db).krate, AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate, - AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.krate, + AttrDefId::EnumVariantId(it) => it.lookup(db).parent.module(db).krate, AttrDefId::StaticId(it) => it.lookup(db).module(db).krate, AttrDefId::ConstId(it) => it.lookup(db).module(db).krate, AttrDefId::TraitId(it) => it.lookup(db).container.krate, diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 53644f58efc..7eb2f3adddb 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 a18ac4b28c4..893ad47e241 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -3,7 +3,7 @@ //! `DefCollector::collect` contains the fixed-point iteration loop which //! resolves imports and expands macros. -use std::{cmp::Ordering, iter, mem}; +use std::{cmp::Ordering, iter, mem, ops::Not}; use base_db::{CrateId, Dependency, Edition, FileId}; use cfg::{CfgExpr, CfgOptions}; @@ -23,7 +23,7 @@ use itertools::{izip, Itertools}; use la_arena::Idx; use limit::Limit; use rustc_hash::{FxHashMap, FxHashSet}; -use span::{Span, SyntaxContextId}; +use span::{ErasedFileAstId, Span, SyntaxContextId}; use stdx::always; use syntax::{ast, SmolStr}; use triomphe::Arc; @@ -35,8 +35,8 @@ use crate::{ derive_macro_as_call_id, item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports}, item_tree::{ - self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, - Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, + self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, + ItemTreeModItemNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, }, macro_call_as_call_id, macro_call_as_call_id_with_eager, nameres::{ @@ -51,7 +51,7 @@ use crate::{ per_ns::PerNs, tt, visibility::{RawVisibility, Visibility}, - AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantId, + AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantLoc, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId, @@ -980,24 +980,26 @@ impl DefCollector<'_> { cov_mark::hit!(glob_enum); // glob import from enum => just import all the variants - // XXX: urgh, so this works by accident! Here, we look at - // the enum data, and, in theory, this might require us to - // look back at the crate_def_map, creating a cycle. For - // example, `enum E { crate::some_macro!(); }`. Luckily, the - // only kind of macro that is allowed inside enum is a - // `cfg_macro`, and we don't need to run name resolution for - // it, but this is sheer luck! - let enum_data = self.db.enum_data(e); - let resolutions = enum_data - .variants - .iter() - .map(|(local_id, variant_data)| { - let name = variant_data.name.clone(); - let variant = EnumVariantId { parent: e, local_id }; - let res = PerNs::both(variant.into(), variant.into(), vis, None); - (Some(name), res) - }) - .collect::>(); + // 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.enum_definitions[&e] + } else { + 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) => { @@ -1577,7 +1579,10 @@ impl ModCollector<'_, '_> { let attrs = self.item_tree.attrs(db, krate, item.into()); if let Some(cfg) = attrs.cfg() { if !self.is_cfg_enabled(&cfg) { - self.emit_unconfigured_diagnostic(item, &cfg); + self.emit_unconfigured_diagnostic( + InFile::new(self.file_id(), item.ast_id(self.item_tree).erase()), + &cfg, + ); return; } } @@ -1708,17 +1713,47 @@ impl ModCollector<'_, '_> { } ModItem::Enum(id) => { let it = &self.item_tree[id]; + let enum_ = + EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } + .intern(db); let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); - update_def( - self.def_collector, - EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } - .intern(db) - .into(), - &it.name, - vis, - false, - ); + update_def(self.def_collector, enum_.into(), &it.name, vis, false); + + let mut index = 0; + let variants = FileItemTreeId::range_iter(it.variants.clone()) + .filter_map(|variant| { + let is_enabled = self + .item_tree + .attrs(db, krate, variant.into()) + .cfg() + .and_then(|cfg| self.is_cfg_enabled(&cfg).not().then_some(cfg)) + .map_or(Ok(()), Err); + match is_enabled { + Err(cfg) => { + self.emit_unconfigured_diagnostic( + InFile::new( + self.file_id(), + self.item_tree[variant.index()].ast_id.erase(), + ), + &cfg, + ); + None + } + Ok(()) => Some({ + let loc = EnumVariantLoc { + id: ItemTreeId::new(self.tree_id, variant), + parent: enum_, + index, + } + .intern(db); + index += 1; + loc + }), + } + }) + .collect(); + self.def_collector.def_map.enum_definitions.insert(enum_, variants); } ModItem::Const(id) => { let it = &self.item_tree[id]; @@ -1905,31 +1940,40 @@ impl ModCollector<'_, '_> { let is_enabled = item_tree .top_level_attrs(db, krate) .cfg() - .map_or(true, |cfg| self.is_cfg_enabled(&cfg)); - if is_enabled { - let module_id = self.push_child_module( - module.name.clone(), - ast_id.value, - Some((file_id, is_mod_rs)), - &self.item_tree[module.visibility], - module_id, - ); - ModCollector { - def_collector: self.def_collector, - macro_depth: self.macro_depth, - module_id, - tree_id: TreeId::new(file_id.into(), None), - item_tree: &item_tree, - mod_dir, + .and_then(|cfg| self.is_cfg_enabled(&cfg).not().then_some(cfg)) + .map_or(Ok(()), Err); + match is_enabled { + Err(cfg) => { + self.emit_unconfigured_diagnostic( + ast_id.map(|it| it.erase()), + &cfg, + ); } - .collect_in_top_module(item_tree.top_level_items()); - let is_macro_use = is_macro_use - || item_tree - .top_level_attrs(db, krate) - .by_key("macro_use") - .exists(); - if is_macro_use { - self.import_all_legacy_macros(module_id); + Ok(()) => { + let module_id = self.push_child_module( + module.name.clone(), + ast_id.value, + Some((file_id, is_mod_rs)), + &self.item_tree[module.visibility], + module_id, + ); + ModCollector { + def_collector: self.def_collector, + macro_depth: self.macro_depth, + module_id, + tree_id: TreeId::new(file_id.into(), None), + item_tree: &item_tree, + mod_dir, + } + .collect_in_top_module(item_tree.top_level_items()); + let is_macro_use = is_macro_use + || item_tree + .top_level_attrs(db, krate) + .by_key("macro_use") + .exists(); + if is_macro_use { + self.import_all_legacy_macros(module_id); + } } } } @@ -2360,10 +2404,7 @@ impl ModCollector<'_, '_> { self.def_collector.cfg_options.check(cfg) != Some(false) } - fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) { - let ast_id = item.ast_id(self.item_tree); - - let ast_id = InFile::new(self.file_id(), ast_id.erase()); + fn emit_unconfigured_diagnostic(&mut self, ast_id: InFile, cfg: &CfgExpr) { self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code( self.module_id, ast_id, diff --git a/crates/hir-def/src/nameres/diagnostics.rs b/crates/hir-def/src/nameres/diagnostics.rs index 9cffb3c9f37..0a3f7bf7ec3 100644 --- a/crates/hir-def/src/nameres/diagnostics.rs +++ b/crates/hir-def/src/nameres/diagnostics.rs @@ -40,6 +40,23 @@ pub enum DefDiagnosticKind { MacroDefError { ast: AstId, message: String }, } +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct DefDiagnostics(Option>>); + +impl DefDiagnostics { + pub fn new(diagnostics: Vec) -> Self { + Self(if diagnostics.is_empty() { + None + } else { + Some(triomphe::Arc::new(diagnostics.into_boxed_slice())) + }) + } + + pub fn iter(&self) -> impl Iterator { + self.0.as_ref().into_iter().flat_map(|it| &***it) + } +} + #[derive(Debug, PartialEq, Eq)] pub struct DefDiagnostic { pub in_module: LocalModuleId, diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index 389dabdbc86..01f79f042f7 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -11,18 +11,18 @@ //! `ReachedFixedPoint` signals about this. use base_db::Edition; -use hir_expand::name::Name; +use hir_expand::{name::Name, Lookup}; use triomphe::Arc; use crate::{ - data::adt::VariantData, db::DefDatabase, item_scope::{ImportOrExternCrate, BUILTIN_SCOPE}, + item_tree::Fields, nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs}, path::{ModPath, PathKind}, per_ns::PerNs, visibility::{RawVisibility, Visibility}, - AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, + AdtId, CrateId, LocalModuleId, ModuleDefId, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -355,29 +355,42 @@ impl DefMap { ModuleDefId::AdtId(AdtId::EnumId(e)) => { // enum variant cov_mark::hit!(can_import_enum_variant); - let enum_data = db.enum_data(e); - match enum_data.variant(segment) { - Some(local_id) => { - let variant = EnumVariantId { parent: e, local_id }; - match &*enum_data.variants[local_id].variant_data { - VariantData::Record(_) => { - PerNs::types(variant.into(), Visibility::Public, None) - } - VariantData::Tuple(_) | VariantData::Unit => PerNs::both( - variant.into(), - variant.into(), - Visibility::Public, - None, - ), + 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.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 => { return ResolvePathResult::with( PerNs::types(e.into(), vis, imp), ReachedFixedPoint::Yes, Some(i), Some(self.krate), - ); + ) } } } diff --git a/crates/hir-def/src/pretty.rs b/crates/hir-def/src/pretty.rs index f4f5541e373..8e0df469701 100644 --- a/crates/hir-def/src/pretty.rs +++ b/crates/hir-def/src/pretty.rs @@ -39,11 +39,9 @@ pub(crate) fn print_path(db: &dyn DefDatabase, path: &Path, buf: &mut dyn Write) LangItemTarget::Trait(it) => { write!(buf, "{}", db.trait_data(it).name.display(db.upcast()))? } - LangItemTarget::EnumVariant(it) => write!( - buf, - "{}", - db.enum_data(it.parent).variants[it.local_id].name.display(db.upcast()) - )?, + LangItemTarget::EnumVariant(it) => { + write!(buf, "{}", db.enum_variant_data(it).name.display(db.upcast()))? + } } if let Some(s) = s { diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 1d850f721c1..bb530259ac5 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -1111,7 +1111,7 @@ impl HasResolver for DefWithBodyId { DefWithBodyId::ConstId(c) => c.resolver(db), DefWithBodyId::FunctionId(f) => f.resolver(db), DefWithBodyId::StaticId(s) => s.resolver(db), - DefWithBodyId::VariantId(v) => v.parent.resolver(db), + DefWithBodyId::VariantId(v) => v.resolver(db), DefWithBodyId::InTypeConstId(c) => c.lookup(db).owner.resolver(db), } } @@ -1137,7 +1137,7 @@ impl HasResolver for GenericDefId { GenericDefId::TraitAliasId(inner) => inner.resolver(db), GenericDefId::TypeAliasId(inner) => inner.resolver(db), GenericDefId::ImplId(inner) => inner.resolver(db), - GenericDefId::EnumVariantId(inner) => inner.parent.resolver(db), + GenericDefId::EnumVariantId(inner) => inner.resolver(db), GenericDefId::ConstId(inner) => inner.resolver(db), } } @@ -1145,14 +1145,14 @@ impl HasResolver for GenericDefId { impl HasResolver for EnumVariantId { fn resolver(self, db: &dyn DefDatabase) -> Resolver { - self.parent.resolver(db) + self.lookup(db).parent.resolver(db) } } impl HasResolver for VariantId { fn resolver(self, db: &dyn DefDatabase) -> Resolver { match self { - VariantId::EnumVariantId(it) => it.parent.resolver(db), + VariantId::EnumVariantId(it) => it.resolver(db), VariantId::StructId(it) => it.resolver(db), VariantId::UnionId(it) => it.resolver(db), } diff --git a/crates/hir-def/src/src.rs b/crates/hir-def/src/src.rs index 3770103cda5..9bd8c8d2215 100644 --- a/crates/hir-def/src/src.rs +++ b/crates/hir-def/src/src.rs @@ -5,8 +5,8 @@ use la_arena::ArenaMap; use syntax::ast; use crate::{ - db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc, Lookup, Macro2Loc, - MacroRulesLoc, ProcMacroLoc, UseId, + db::DefDatabase, item_tree::ItemTreeModItemNode, AssocItemLoc, EnumVariantLoc, ItemLoc, Lookup, + Macro2Loc, MacroRulesLoc, ProcMacroLoc, UseId, }; pub trait HasSource { @@ -14,7 +14,7 @@ pub trait HasSource { fn source(&self, db: &dyn DefDatabase) -> InFile; } -impl HasSource for AssocItemLoc { +impl HasSource for AssocItemLoc { type Value = N::Source; fn source(&self, db: &dyn DefDatabase) -> InFile { @@ -27,7 +27,7 @@ impl HasSource for AssocItemLoc { } } -impl HasSource for ItemLoc { +impl HasSource for ItemLoc { type Value = N::Source; fn source(&self, db: &dyn DefDatabase) -> InFile { @@ -40,6 +40,19 @@ impl HasSource for ItemLoc { } } +impl HasSource for EnumVariantLoc { + type Value = ast::Variant; + + fn source(&self, db: &dyn DefDatabase) -> InFile { + let tree = self.id.item_tree(db); + let ast_id_map = db.ast_id_map(self.id.file_id()); + let root = db.parse_or_expand(self.id.file_id()); + let node = &tree[self.id.value]; + + InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id).to_node(&root)) + } +} + impl HasSource for Macro2Loc { type Value = ast::MacroDef; diff --git a/crates/hir-def/src/trace.rs b/crates/hir-def/src/trace.rs index 6e6ceb8e474..04d5b266194 100644 --- a/crates/hir-def/src/trace.rs +++ b/crates/hir-def/src/trace.rs @@ -18,6 +18,7 @@ pub(crate) struct Trace { } impl Trace { + #[allow(dead_code)] pub(crate) fn new_for_arena() -> Trace { Trace { arena: Some(Arena::default()), map: None, len: 0 } } @@ -41,6 +42,7 @@ impl Trace { id } + #[allow(dead_code)] pub(crate) fn into_arena(mut self) -> Arena { self.arena.take().unwrap() } diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs index cd8023f5d7d..3294ce29a4a 100644 --- a/crates/hir-def/src/visibility.rs +++ b/crates/hir-def/src/visibility.rs @@ -222,13 +222,7 @@ pub(crate) fn field_visibilities_query( db: &dyn DefDatabase, variant_id: VariantId, ) -> Arc> { - let var_data = match variant_id { - VariantId::StructId(it) => db.struct_data(it).variant_data.clone(), - VariantId::UnionId(it) => db.union_data(it).variant_data.clone(), - VariantId::EnumVariantId(it) => { - db.enum_data(it.parent).variants[it.local_id].variant_data.clone() - } - }; + let var_data = variant_id.variant_data(db); let resolver = variant_id.module(db).resolver(db); let mut res = ArenaMap::default(); for (field_id, field_data) in var_data.fields().iter() { diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index ed04582cb0a..035664c6446 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -218,6 +218,9 @@ pub fn real_span_map(db: &dyn ExpandDatabase, file_id: FileId) -> Arc { - let prev_variant = EnumVariantId { local_id, parent: variant_id.parent }; - 1 + db.const_eval_discriminant(prev_variant)? + Some(prev_idx) => { + 1 + db.const_eval_discriminant( + db.enum_data(loc.parent).variants[prev_idx as usize].0, + )? } _ => 0, }; diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs index 726069f20c0..9fc76550aa6 100644 --- a/crates/hir-ty/src/db.rs +++ b/crates/hir-ty/src/db.rs @@ -292,7 +292,7 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc .display(db.upcast()) .to_string(), DefWithBodyId::VariantId(it) => { - db.enum_data(it.parent).variants[it.local_id].name.display(db.upcast()).to_string() + db.enum_variant_data(it).name.display(db.upcast()).to_string() } DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"), }); diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs index 51a044d8ef5..7ea1b9e4213 100644 --- a/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/crates/hir-ty/src/diagnostics/decl_check.rs @@ -582,11 +582,11 @@ impl<'a> DeclValidator<'a> { // Check the field names. let enum_fields_replacements = data .variants - .values() - .filter_map(|variant| { + .iter() + .filter_map(|(_, name)| { Some(Replacement { - current_name: variant.name.clone(), - suggested_text: to_camel_case(&variant.name.to_smol_str())?, + current_name: name.clone(), + suggested_text: to_camel_case(&name.to_smol_str())?, expected_case: CaseType::UpperCamelCase, }) }) diff --git a/crates/hir-ty/src/diagnostics/match_check.rs b/crates/hir-ty/src/diagnostics/match_check.rs index 2e04bbfee83..e4d4536fc93 100644 --- a/crates/hir-ty/src/diagnostics/match_check.rs +++ b/crates/hir-ty/src/diagnostics/match_check.rs @@ -318,8 +318,7 @@ impl HirDisplay for Pat { if let Some(variant) = variant { match variant { VariantId::EnumVariantId(v) => { - let data = f.db.enum_data(v.parent); - write!(f, "{}", data.variants[v.local_id].name.display(f.db.upcast()))?; + write!(f, "{}", f.db.enum_variant_data(v).name.display(f.db.upcast()))?; } VariantId::StructId(s) => { write!(f, "{}", f.db.struct_data(s).name.display(f.db.upcast()))? diff --git a/crates/hir-ty/src/diagnostics/match_check/deconstruct_pat.rs b/crates/hir-ty/src/diagnostics/match_check/deconstruct_pat.rs index a0f6b9368ee..f066f8b798d 100644 --- a/crates/hir-ty/src/diagnostics/match_check/deconstruct_pat.rs +++ b/crates/hir-ty/src/diagnostics/match_check/deconstruct_pat.rs @@ -594,7 +594,7 @@ impl SplitWildcard { let mut ctors: SmallVec<[_; 1]> = enum_data .variants .iter() - .map(|(local_id, _)| EnumVariantId { parent: *enum_id, local_id }) + .map(|&(variant, _)| variant) .filter(|&variant| { // If `exhaustive_patterns` is enabled, we exclude variants known to be // uninhabited. diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index e2ba221cf12..3a0ec6a582c 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -20,8 +20,7 @@ use hir_def::{ path::{Path, PathKind}, type_ref::{TraitBoundModifier, TypeBound, TypeRef}, visibility::Visibility, - EnumVariantId, HasModule, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId, - TraitId, + HasModule, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId, TraitId, }; use hir_expand::name::Name; use intern::{Internable, Interned}; @@ -613,10 +612,9 @@ fn render_const_scalar( else { return f.write_str(""); }; - let data = &f.db.enum_data(e).variants[var_id]; + let data = f.db.enum_variant_data(var_id); write!(f, "{}", data.name.display(f.db.upcast()))?; - let field_types = - f.db.field_types(EnumVariantId { parent: e, local_id: var_id }.into()); + let field_types = f.db.field_types(var_id.into()); render_variant_after_name( &data.variant_data, f, @@ -892,11 +890,9 @@ impl HirDisplay for Ty { CallableDefId::StructId(s) => { write!(f, "{}", db.struct_data(s).name.display(f.db.upcast()))? } - CallableDefId::EnumVariantId(e) => write!( - f, - "{}", - db.enum_data(e.parent).variants[e.local_id].name.display(f.db.upcast()) - )?, + CallableDefId::EnumVariantId(e) => { + write!(f, "{}", db.enum_variant_data(e).name.display(f.db.upcast()))? + } }; f.end_location_link(); if parameters.len(Interner) > 0 { diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 3de39584404..2aff53a4acd 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -40,8 +40,8 @@ use hir_def::{ path::{ModPath, Path}, resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs}, type_ref::TypeRef, - AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, ItemContainerId, Lookup, - TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId, + AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, Lookup, TraitId, + TupleFieldId, TupleId, TypeAliasId, VariantId, }; use hir_expand::name::{name, Name}; use indexmap::IndexSet; @@ -87,28 +87,30 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc ctx.collect_const(&db.const_data(c)), DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)), DefWithBodyId::VariantId(v) => { - ctx.return_ty = TyBuilder::builtin(match db.enum_data(v.parent).variant_body_type() { - hir_def::layout::IntegerType::Pointer(signed) => match signed { - true => BuiltinType::Int(BuiltinInt::Isize), - false => BuiltinType::Uint(BuiltinUint::Usize), + ctx.return_ty = TyBuilder::builtin( + match db.enum_data(v.lookup(db.upcast()).parent.into()).variant_body_type() { + hir_def::layout::IntegerType::Pointer(signed) => match signed { + true => BuiltinType::Int(BuiltinInt::Isize), + false => BuiltinType::Uint(BuiltinUint::Usize), + }, + hir_def::layout::IntegerType::Fixed(size, signed) => match signed { + true => BuiltinType::Int(match size { + Integer::I8 => BuiltinInt::I8, + Integer::I16 => BuiltinInt::I16, + Integer::I32 => BuiltinInt::I32, + Integer::I64 => BuiltinInt::I64, + Integer::I128 => BuiltinInt::I128, + }), + false => BuiltinType::Uint(match size { + Integer::I8 => BuiltinUint::U8, + Integer::I16 => BuiltinUint::U16, + Integer::I32 => BuiltinUint::U32, + Integer::I64 => BuiltinUint::U64, + Integer::I128 => BuiltinUint::U128, + }), + }, }, - hir_def::layout::IntegerType::Fixed(size, signed) => match signed { - true => BuiltinType::Int(match size { - Integer::I8 => BuiltinInt::I8, - Integer::I16 => BuiltinInt::I16, - Integer::I32 => BuiltinInt::I32, - Integer::I64 => BuiltinInt::I64, - Integer::I128 => BuiltinInt::I128, - }), - false => BuiltinType::Uint(match size { - Integer::I8 => BuiltinUint::U8, - Integer::I16 => BuiltinUint::U16, - Integer::I32 => BuiltinUint::U32, - Integer::I64 => BuiltinUint::U64, - Integer::I128 => BuiltinUint::U128, - }), - }, - }); + ); } DefWithBodyId::InTypeConstId(c) => { // FIXME(const-generic-body): We should not get the return type in this way. @@ -1062,7 +1064,7 @@ impl<'a> InferenceContext<'a> { Some(ResolveValueResult::ValueNs(value, _)) => match value { ValueNs::EnumVariantId(var) => { let substs = ctx.substs_from_path(path, var.into(), true); - let ty = self.db.ty(var.parent.into()); + let ty = self.db.ty(var.lookup(self.db.upcast()).parent.into()); let ty = self.insert_type_vars(ty.substitute(Interner, &substs)); return (ty, Some(var.into())); } @@ -1105,7 +1107,7 @@ impl<'a> InferenceContext<'a> { } TypeNs::EnumVariantId(var) => { let substs = ctx.substs_from_path(path, var.into(), true); - let ty = self.db.ty(var.parent.into()); + let ty = self.db.ty(var.lookup(self.db.upcast()).parent.into()); let ty = self.insert_type_vars(ty.substitute(Interner, &substs)); forbid_unresolved_segments((ty, Some(var.into())), unresolved) } @@ -1131,8 +1133,7 @@ impl<'a> InferenceContext<'a> { if let Some((AdtId::EnumId(id), _)) = ty.as_adt() { let enum_data = self.db.enum_data(id); let name = current_segment.first().unwrap().name; - if let Some(local_id) = enum_data.variant(name) { - let variant = EnumVariantId { parent: id, local_id }; + if let Some(variant) = enum_data.variant(name) { return if remaining_segments.len() == 1 { (ty, Some(variant.into())) } else { @@ -1247,8 +1248,7 @@ impl<'a> InferenceContext<'a> { // this could be an enum variant or associated type if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() { let enum_data = self.db.enum_data(enum_id); - if let Some(local_id) = enum_data.variant(segment) { - let variant = EnumVariantId { parent: enum_id, local_id }; + if let Some(variant) = enum_data.variant(segment) { return (ty, Some(variant.into())); } } diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 3bf0a00cd11..c194270b91e 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -666,7 +666,7 @@ impl InferenceContext<'_> { | Pat::Or(_) => (), Pat::TupleStruct { .. } | Pat::Record { .. } => { if let Some(variant) = self.result.variant_resolution_for_pat(p) { - let adt = variant.adt_id(); + let adt = variant.adt_id(self.db.upcast()); let is_multivariant = match adt { hir_def::AdtId::EnumId(e) => self.db.enum_data(e).variants.len() != 1, _ => false, diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs index e61a070265a..a09bb15147f 100644 --- a/crates/hir-ty/src/infer/path.rs +++ b/crates/hir-ty/src/infer/path.rs @@ -4,7 +4,7 @@ use chalk_ir::cast::Cast; use hir_def::{ path::{Path, PathSegment}, resolver::{ResolveValueResult, TypeNs, ValueNs}, - AdtId, AssocItemId, EnumVariantId, GenericDefId, ItemContainerId, Lookup, + AdtId, AssocItemId, GenericDefId, ItemContainerId, Lookup, }; use hir_expand::name::Name; use stdx::never; @@ -395,8 +395,7 @@ impl InferenceContext<'_> { _ => return None, }; let enum_data = self.db.enum_data(enum_id); - let local_id = enum_data.variant(name)?; - let variant = EnumVariantId { parent: enum_id, local_id }; + let variant = enum_data.variant(name)?; self.write_variant_resolution(id, variant.into()); Some((ValueNs::EnumVariantId(variant), subst.clone())) } diff --git a/crates/hir-ty/src/inhabitedness.rs b/crates/hir-ty/src/inhabitedness.rs index e5038543b68..a63556f450d 100644 --- a/crates/hir-ty/src/inhabitedness.rs +++ b/crates/hir-ty/src/inhabitedness.rs @@ -7,7 +7,7 @@ use chalk_ir::{ }; use hir_def::{ attr::Attrs, data::adt::VariantData, visibility::Visibility, AdtId, EnumVariantId, HasModule, - Lookup, ModuleId, VariantId, + ModuleId, VariantId, }; use rustc_hash::FxHashSet; @@ -30,17 +30,15 @@ pub(crate) fn is_enum_variant_uninhabited_from( target_mod: ModuleId, db: &dyn HirDatabase, ) -> bool { - let enum_data = db.enum_data(variant.parent); - let vars_attrs = db.variants_attrs(variant.parent); - let is_local = variant.parent.lookup(db.upcast()).container.krate() == target_mod.krate(); + let is_local = variant.module(db.upcast()).krate() == target_mod.krate(); let mut uninhabited_from = UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default() }; let inhabitedness = uninhabited_from.visit_variant( variant.into(), - &enum_data.variants[variant.local_id].variant_data, + &db.enum_variant_data(variant).variant_data, subst, - &vars_attrs[variant.local_id], + &db.attrs(variant.into()), is_local, ); inhabitedness == BREAK_VISIBLY_UNINHABITED @@ -117,15 +115,14 @@ impl UninhabitedFrom<'_> { self.visit_variant(s.into(), &struct_data.variant_data, subst, &attrs, is_local) } AdtId::EnumId(e) => { - let vars_attrs = self.db.variants_attrs(e); let enum_data = self.db.enum_data(e); - for (local_id, enum_var) in enum_data.variants.iter() { + for &(variant, _) in enum_data.variants.iter() { let variant_inhabitedness = self.visit_variant( - EnumVariantId { parent: e, local_id }.into(), - &enum_var.variant_data, + variant.into(), + &self.db.enum_variant_data(variant).variant_data, subst, - &vars_attrs[local_id], + &self.db.attrs(variant.into()), is_local, ); match variant_inhabitedness { diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs index 875906f9abd..5c7decb6892 100644 --- a/crates/hir-ty/src/layout.rs +++ b/crates/hir-ty/src/layout.rs @@ -9,7 +9,7 @@ use hir_def::{ Abi, FieldsShape, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions, Scalar, Size, StructKind, TargetDataLayout, WrappingRange, }, - LocalEnumVariantId, LocalFieldId, StructId, + LocalFieldId, StructId, }; use la_arena::{Idx, RawIdx}; use rustc_abi::AddressSpace; @@ -32,15 +32,15 @@ mod adt; mod target; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct RustcEnumVariantIdx(pub LocalEnumVariantId); +pub struct RustcEnumVariantIdx(pub usize); impl rustc_index::Idx for RustcEnumVariantIdx { fn new(idx: usize) -> Self { - RustcEnumVariantIdx(Idx::from_raw(RawIdx::from(idx as u32))) + RustcEnumVariantIdx(idx) } fn index(self) -> usize { - u32::from(self.0.into_raw()) as usize + self.0 } } diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs index 8a7715ce872..9fcc251356f 100644 --- a/crates/hir-ty/src/layout/adt.rs +++ b/crates/hir-ty/src/layout/adt.rs @@ -6,9 +6,8 @@ use base_db::salsa::Cycle; use hir_def::{ data::adt::VariantData, layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout}, - AdtId, EnumVariantId, LocalEnumVariantId, VariantId, + AdtId, VariantId, }; -use la_arena::RawIdx; use rustc_index::IndexVec; use smallvec::SmallVec; use triomphe::Arc; @@ -22,8 +21,8 @@ use crate::{ use super::LayoutCx; -pub(crate) const fn struct_variant_idx() -> RustcEnumVariantIdx { - RustcEnumVariantIdx(LocalEnumVariantId::from_raw(RawIdx::from_u32(0))) +pub(crate) fn struct_variant_idx() -> RustcEnumVariantIdx { + RustcEnumVariantIdx(0) } pub fn layout_of_adt_query( @@ -62,12 +61,7 @@ pub fn layout_of_adt_query( let r = data .variants .iter() - .map(|(idx, v)| { - handle_variant( - EnumVariantId { parent: e, local_id: idx }.into(), - &v.variant_data, - ) - }) + .map(|&(v, _)| handle_variant(v.into(), &db.enum_variant_data(v).variant_data)) .collect::, _>>()?; (r, data.repr.unwrap_or_default()) } @@ -89,8 +83,7 @@ pub fn layout_of_adt_query( |min, max| repr_discr(&dl, &repr, min, max).unwrap_or((Integer::I8, false)), variants.iter_enumerated().filter_map(|(id, _)| { let AdtId::EnumId(e) = def else { return None }; - let d = - db.const_eval_discriminant(EnumVariantId { parent: e, local_id: id.0 }).ok()?; + let d = db.const_eval_discriminant(db.enum_data(e).variants[id.0].0).ok()?; Some((id, d)) }), // FIXME: The current code for niche-filling relies on variant indices diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index e371e427615..f66b584e3b5 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -762,7 +762,7 @@ impl<'a> TyLoweringContext<'a> { Some(segment) if segment.args_and_bindings.is_some() => Some(segment), _ => last, }; - (segment, Some(var.parent.into())) + (segment, Some(var.lookup(self.db.upcast()).parent.into())) } }; if let Some(segment) = segment { @@ -1375,11 +1375,13 @@ pub(crate) fn field_types_query( let (resolver, def): (_, GenericDefId) = match variant_id { VariantId::StructId(it) => (it.resolver(db.upcast()), it.into()), VariantId::UnionId(it) => (it.resolver(db.upcast()), it.into()), - VariantId::EnumVariantId(it) => (it.parent.resolver(db.upcast()), it.parent.into()), + VariantId::EnumVariantId(it) => { + (it.resolver(db.upcast()), it.lookup(db.upcast()).parent.into()) + } }; let generics = generics(db.upcast(), def); let mut res = ArenaMap::default(); - let ctx = TyLoweringContext::new(db, &resolver, GenericDefId::from(variant_id.adt_id()).into()) + let ctx = TyLoweringContext::new(db, &resolver, def.into()) .with_type_param_mode(ParamLoweringMode::Variable); for (field_id, field_data) in var_data.fields().iter() { res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(&field_data.type_ref))); @@ -1727,44 +1729,50 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS /// Build the type of a tuple struct constructor. fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders { let struct_data = db.struct_data(def); - if let StructKind::Unit = struct_data.variant_data.kind() { - return type_for_adt(db, def.into()); + match struct_data.variant_data.kind() { + StructKind::Record => unreachable!("callers check for valueness of variant"), + StructKind::Unit => return type_for_adt(db, def.into()), + StructKind::Tuple => { + let generics = generics(db.upcast(), AdtId::from(def).into()); + let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); + make_binders( + db, + &generics, + TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(Interner), + ) + } } - let generics = generics(db.upcast(), AdtId::from(def).into()); - let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); - make_binders( - db, - &generics, - TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(Interner), - ) } fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig { - let enum_data = db.enum_data(def.parent); - let var_data = &enum_data.variants[def.local_id]; + let var_data = db.enum_variant_data(def); let fields = var_data.variant_data.fields(); - let resolver = def.parent.resolver(db.upcast()); + let resolver = def.resolver(db.upcast()); let ctx = TyLoweringContext::new(db, &resolver, DefWithBodyId::VariantId(def).into()) .with_type_param_mode(ParamLoweringMode::Variable); let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::>(); - let (ret, binders) = type_for_adt(db, def.parent.into()).into_value_and_skipped_binders(); + let (ret, binders) = + type_for_adt(db, def.lookup(db.upcast()).parent.into()).into_value_and_skipped_binders(); Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe)) } /// Build the type of a tuple enum variant constructor. fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> Binders { - let enum_data = db.enum_data(def.parent); - let var_data = &enum_data.variants[def.local_id].variant_data; - if let StructKind::Unit = var_data.kind() { - return type_for_adt(db, def.parent.into()); + let e = def.lookup(db.upcast()).parent; + match db.enum_variant_data(def).variant_data.kind() { + StructKind::Record => unreachable!("callers check for valueness of variant"), + StructKind::Unit => return type_for_adt(db, e.into()), + StructKind::Tuple => { + let generics = generics(db.upcast(), e.into()); + let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); + make_binders( + db, + &generics, + TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs) + .intern(Interner), + ) + } } - let generics = generics(db.upcast(), def.parent.into()); - let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); - make_binders( - db, - &generics, - TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs).intern(Interner), - ) } fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders { @@ -1812,7 +1820,7 @@ impl CallableDefId { match self { CallableDefId::FunctionId(f) => f.lookup(db).module(db), CallableDefId::StructId(s) => s.lookup(db).container, - CallableDefId::EnumVariantId(e) => e.parent.lookup(db).container, + CallableDefId::EnumVariantId(e) => e.module(db), } .krate() } @@ -1893,12 +1901,8 @@ pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Binders } pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binders { - let impl_loc = impl_id.lookup(db.upcast()); let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db.upcast()); - let _cx = stdx::panic_context::enter(format!( - "impl_self_ty_query({impl_id:?} -> {impl_loc:?} -> {impl_data:?})" - )); let generics = generics(db.upcast(), impl_id.into()); let ctx = TyLoweringContext::new(db, &resolver, impl_id.into()) .with_type_param_mode(ParamLoweringMode::Variable); @@ -1930,12 +1934,8 @@ pub(crate) fn impl_self_ty_recover( } pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option> { - let impl_loc = impl_id.lookup(db.upcast()); let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db.upcast()); - let _cx = stdx::panic_context::enter(format!( - "impl_trait_query({impl_id:?} -> {impl_loc:?} -> {impl_data:?})" - )); let ctx = TyLoweringContext::new(db, &resolver, impl_id.into()) .with_type_param_mode(ParamLoweringMode::Variable); let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders(); diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 482d61f6959..551446962d1 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -752,7 +752,7 @@ impl Evaluator<'_> { Variants::Multiple { variants, .. } => { &variants[match f.parent { hir_def::VariantId::EnumVariantId(it) => { - RustcEnumVariantIdx(it.local_id) + RustcEnumVariantIdx(it.lookup(self.db.upcast()).index as usize) } _ => { return Err(MirEvalError::TypeError( @@ -1412,22 +1412,12 @@ impl Evaluator<'_> { fn compute_discriminant(&self, ty: Ty, bytes: &[u8]) -> Result { let layout = self.layout(&ty)?; - let enum_id = 'b: { - match ty.kind(Interner) { - TyKind::Adt(e, _) => match e.0 { - AdtId::EnumId(e) => break 'b e, - _ => (), - }, - _ => (), - } + let &TyKind::Adt(chalk_ir::AdtId(AdtId::EnumId(e)), _) = ty.kind(Interner) else { return Ok(0); }; match &layout.variants { Variants::Single { index } => { - let r = self.const_eval_discriminant(EnumVariantId { - parent: enum_id, - local_id: index.0, - })?; + let r = self.const_eval_discriminant(self.db.enum_data(e).variants[index.0].0)?; Ok(r) } Variants::Multiple { tag, tag_encoding, variants, .. } => { @@ -1446,17 +1436,15 @@ impl Evaluator<'_> { let candidate_tag = i128::from_le_bytes(pad16(tag, false)) .wrapping_sub(*niche_start as i128) as usize; - let variant = variants + let idx = variants .iter_enumerated() .map(|(it, _)| it) .filter(|it| it != untagged_variant) .nth(candidate_tag) .unwrap_or(*untagged_variant) .0; - let result = self.const_eval_discriminant(EnumVariantId { - parent: enum_id, - local_id: variant, - })?; + let result = + self.const_eval_discriminant(self.db.enum_data(e).variants[idx].0)?; Ok(result) } } @@ -1579,14 +1567,16 @@ impl Evaluator<'_> { subst: Substitution, locals: &Locals, ) -> Result<(usize, Arc, Option<(usize, usize, i128)>)> { - let adt = it.adt_id(); + let adt = it.adt_id(self.db.upcast()); if let DefWithBodyId::VariantId(f) = locals.body.owner { if let VariantId::EnumVariantId(it) = it { - if AdtId::from(f.parent) == adt { - // Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and - // infinite sized type errors) we use a dummy layout - let i = self.const_eval_discriminant(it)?; - return Ok((16, self.layout(&TyBuilder::unit())?, Some((0, 16, i)))); + if let AdtId::EnumId(e) = adt { + if f.lookup(self.db.upcast()).parent == e { + // Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and + // infinite sized type errors) we use a dummy layout + let i = self.const_eval_discriminant(it)?; + return Ok((16, self.layout(&TyBuilder::unit())?, Some((0, 16, i)))); + } } } } @@ -1602,8 +1592,9 @@ impl Evaluator<'_> { VariantId::EnumVariantId(it) => it, _ => not_supported!("multi variant layout for non-enums"), }; - let rustc_enum_variant_idx = RustcEnumVariantIdx(enum_variant_id.local_id); let mut discriminant = self.const_eval_discriminant(enum_variant_id)?; + let lookup = enum_variant_id.lookup(self.db.upcast()); + let rustc_enum_variant_idx = RustcEnumVariantIdx(lookup.index as usize); let variant_layout = variants[rustc_enum_variant_idx].clone(); let have_tag = match tag_encoding { TagEncoding::Direct => true, @@ -1847,8 +1838,8 @@ impl Evaluator<'_> { .then(|| (layout.size.bytes_usize(), layout.align.abi.bytes() as usize))); } if let DefWithBodyId::VariantId(f) = locals.body.owner { - if let Some((adt, _)) = ty.as_adt() { - if AdtId::from(f.parent) == adt { + if let Some((AdtId::EnumId(e), _)) = ty.as_adt() { + if f.lookup(self.db.upcast()).parent == e { // Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and // infinite sized type errors) we use a dummy size return Ok(Some((16, 16))); @@ -2019,10 +2010,8 @@ impl Evaluator<'_> { bytes, e, ) { - let data = &this.db.enum_data(e).variants[v].variant_data; - let field_types = this - .db - .field_types(EnumVariantId { parent: e, local_id: v }.into()); + let data = &this.db.enum_variant_data(v).variant_data; + let field_types = this.db.field_types(v.into()); for (f, _) in data.fields().iter() { let offset = l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize(); @@ -2093,14 +2082,13 @@ impl Evaluator<'_> { } AdtId::UnionId(_) => (), AdtId::EnumId(e) => { - if let Some((variant, layout)) = detect_variant_from_bytes( + if let Some((ev, layout)) = detect_variant_from_bytes( &layout, self.db, self.trait_env.clone(), self.read_memory(addr, layout.size.bytes_usize())?, e, ) { - let ev = EnumVariantId { parent: e, local_id: variant }; for (i, (_, ty)) in self.db.field_types(ev.into()).iter().enumerate() { let offset = layout.fields.offset(i).bytes_usize(); let ty = ty.clone().substitute(Interner, subst); @@ -2540,11 +2528,13 @@ impl Evaluator<'_> { match r { Ok(r) => Ok(r), Err(e) => { - let data = self.db.enum_data(variant.parent); + let db = self.db.upcast(); + let loc = variant.lookup(db); + let enum_loc = loc.parent.lookup(db); let name = format!( "{}::{}", - data.name.display(self.db.upcast()), - data.variants[variant.local_id].name.display(self.db.upcast()) + enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast()), + loc.id.item_tree(db)[loc.id.value].name.display(db.upcast()), ); Err(MirEvalError::ConstEvalError(name, Box::new(e))) } diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index c02c5ef8767..749ca43fba7 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -69,6 +69,7 @@ struct MirLowerCtx<'a> { drop_scopes: Vec, } +// FIXME: Make this smaller, its stored in database queries #[derive(Debug, Clone, PartialEq, Eq)] pub enum MirLowerError { ConstEvalError(Box, Box), @@ -456,9 +457,8 @@ impl<'ctx> MirLowerCtx<'ctx> { Ok(Some(current)) } ValueNs::EnumVariantId(variant_id) => { - let variant_data = - &self.db.enum_data(variant_id.parent).variants[variant_id.local_id]; - if variant_data.variant_data.kind() == StructKind::Unit { + let variant_data = &self.db.enum_variant_data(variant_id).variant_data; + if variant_data.kind() == StructKind::Unit { let ty = self.infer.type_of_expr[expr_id].clone(); current = self.lower_enum_variant( variant_id, @@ -1874,11 +1874,13 @@ impl<'ctx> MirLowerCtx<'ctx> { match r { Ok(r) => Ok(r), Err(e) => { - let data = self.db.enum_data(variant.parent); + let db = self.db.upcast(); + let loc = variant.lookup(db); + let enum_loc = loc.parent.lookup(db); let name = format!( "{}::{}", - data.name.display(self.db.upcast()), - data.variants[variant.local_id].name.display(self.db.upcast()) + enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast()), + loc.id.item_tree(db)[loc.id.value].name.display(db.upcast()), ); Err(MirLowerError::ConstEvalError(name.into(), Box::new(e))) } @@ -2104,7 +2106,7 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result { - db.enum_data(it.parent).variants[it.local_id].name.display(db.upcast()).to_string() + db.enum_variant_data(it).name.display(db.upcast()).to_string() } DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"), }); diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index 98c2e7c63bc..bbb513b24cb 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -524,22 +524,9 @@ impl MirLowerCtx<'_> { ); current = next; } - let enum_data = self.db.enum_data(v.parent); self.pattern_matching_variant_fields( shape, - &enum_data.variants[v.local_id].variant_data, - variant, - current, - current_else, - &cond_place, - mode, - )? - } - VariantId::StructId(s) => { - let struct_data = self.db.struct_data(s); - self.pattern_matching_variant_fields( - shape, - &struct_data.variant_data, + &self.db.enum_variant_data(v).variant_data, variant, current, current_else, @@ -547,6 +534,15 @@ impl MirLowerCtx<'_> { mode, )? } + VariantId::StructId(s) => self.pattern_matching_variant_fields( + shape, + &self.db.struct_data(s).variant_data, + variant, + current, + current_else, + &cond_place, + mode, + )?, VariantId::UnionId(_) => { return Err(MirLowerError::TypeError("pattern matching on union")) } diff --git a/crates/hir-ty/src/mir/pretty.rs b/crates/hir-ty/src/mir/pretty.rs index 366c2f662b5..65fb5884825 100644 --- a/crates/hir-ty/src/mir/pretty.rs +++ b/crates/hir-ty/src/mir/pretty.rs @@ -7,7 +7,7 @@ use std::{ use either::Either; use hir_def::{body::Body, hir::BindingId}; -use hir_expand::name::Name; +use hir_expand::{name::Name, Lookup}; use la_arena::ArenaMap; use crate::{ @@ -58,8 +58,14 @@ impl MirBody { ); } hir_def::DefWithBodyId::VariantId(id) => { - let data = db.enum_data(id.parent); - w!(this, "enum {} = ", data.name.display(db.upcast())); + let loc = id.lookup(db.upcast()); + let enum_loc = loc.parent.lookup(db.upcast()); + w!( + this, + "enum {}::{} = ", + enum_loc.id.item_tree(db.upcast())[enum_loc.id.value].name.display(db.upcast()), + loc.id.item_tree(db.upcast())[loc.id.value].name.display(db.upcast()), + ) } hir_def::DefWithBodyId::InTypeConstId(id) => { w!(this, "in type const {id:?} = "); @@ -306,8 +312,7 @@ impl<'a> MirPrettyCtx<'a> { hir_def::VariantId::EnumVariantId(e) => { w!(this, "("); f(this, local, head); - let variant_name = - &this.db.enum_data(e.parent).variants[e.local_id].name; + let variant_name = &this.db.enum_variant_data(e).name; w!( this, " as {}).{}", diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs index c8cc61cc21b..671fd9ec3a4 100644 --- a/crates/hir-ty/src/tests.rs +++ b/crates/hir-ty/src/tests.rs @@ -16,7 +16,7 @@ use base_db::{FileRange, SourceDatabaseExt}; use expect_test::Expect; use hir_def::{ body::{Body, BodySourceMap, SyntheticSyntax}, - db::{DefDatabase, InternDatabase}, + db::DefDatabase, hir::{ExprId, Pat, PatId}, item_scope::ItemScope, nameres::DefMap, @@ -145,7 +145,7 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour loc.source(&db).value.syntax().text_range().start() } DefWithBodyId::VariantId(it) => { - let loc = db.lookup_intern_enum(it.parent); + let loc = it.lookup(&db); loc.source(&db).value.syntax().text_range().start() } DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(), @@ -383,7 +383,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { loc.source(&db).value.syntax().text_range().start() } DefWithBodyId::VariantId(it) => { - let loc = db.lookup_intern_enum(it.parent); + let loc = it.lookup(&db); loc.source(&db).value.syntax().text_range().start() } DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(), @@ -453,16 +453,12 @@ fn visit_module( visit_body(db, &body, cb); } ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => { - db.enum_data(it) - .variants - .iter() - .map(|(id, _)| hir_def::EnumVariantId { parent: it, local_id: id }) - .for_each(|it| { - let def = it.into(); - cb(def); - let body = db.body(def); - visit_body(db, &body, cb); - }); + db.enum_data(it).variants.iter().for_each(|&(it, _)| { + let def = it.into(); + cb(def); + let body = db.body(def); + visit_body(db, &body, cb); + }); } ModuleDefId::TraitId(it) => { let trait_data = db.trait_data(it); diff --git a/crates/hir-ty/src/tls.rs b/crates/hir-ty/src/tls.rs index 83814ed0ec1..db5fa320577 100644 --- a/crates/hir-ty/src/tls.rs +++ b/crates/hir-ty/src/tls.rs @@ -107,10 +107,7 @@ impl DebugContext<'_> { let name = match def { CallableDefId::FunctionId(ff) => self.0.function_data(ff).name.clone(), CallableDefId::StructId(s) => self.0.struct_data(s).name.clone(), - CallableDefId::EnumVariantId(e) => { - let enum_data = self.0.enum_data(e.parent); - enum_data.variants[e.local_id].name.clone() - } + CallableDefId::EnumVariantId(e) => self.0.enum_variant_data(e).name.clone(), }; match def { CallableDefId::FunctionId(_) => write!(fmt, "{{fn {}}}", name.display(self.0.upcast())), diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index 75b8b9afa70..e80eab87009 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -19,9 +19,8 @@ use hir_def::{ lang_item::LangItem, resolver::{HasResolver, TypeNs}, type_ref::{TraitBoundModifier, TypeRef}, - ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId, - LocalEnumVariantId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId, - TypeParamId, + ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId, Lookup, + OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, }; use hir_expand::name::Name; use intern::Interned; @@ -355,7 +354,7 @@ fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option it.lookup(db).container, GenericDefId::TypeAliasId(it) => it.lookup(db).container, GenericDefId::ConstId(it) => it.lookup(db).container, - GenericDefId::EnumVariantId(it) => return Some(it.parent.into()), + GenericDefId::EnumVariantId(it) => return Some(it.lookup(db).parent.into()), GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) @@ -435,10 +434,12 @@ pub(crate) fn detect_variant_from_bytes<'a>( trait_env: Arc, b: &[u8], e: EnumId, -) -> Option<(LocalEnumVariantId, &'a Layout)> { +) -> Option<(EnumVariantId, &'a Layout)> { let krate = trait_env.krate; let (var_id, var_layout) = match &layout.variants { - hir_def::layout::Variants::Single { index } => (index.0, &*layout), + hir_def::layout::Variants::Single { index } => { + (db.enum_data(e).variants[index.0].0, &*layout) + } hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => { let target_data_layout = db.target_data_layout(krate)?; let size = tag.size(&*target_data_layout).bytes_usize(); @@ -446,11 +447,12 @@ pub(crate) fn detect_variant_from_bytes<'a>( let tag = i128::from_le_bytes(pad16(&b[offset..offset + size], false)); match tag_encoding { TagEncoding::Direct => { - let x = variants.iter_enumerated().find(|x| { - db.const_eval_discriminant(EnumVariantId { parent: e, local_id: x.0 .0 }) - == Ok(tag) - })?; - (x.0 .0, x.1) + let (var_idx, layout) = + variants.iter_enumerated().find_map(|(var_idx, v)| { + let def = db.enum_data(e).variants[var_idx.0].0; + (db.const_eval_discriminant(def) == Ok(tag)).then_some((def, v)) + })?; + (var_idx, layout) } TagEncoding::Niche { untagged_variant, niche_start, .. } => { let candidate_tag = tag.wrapping_sub(*niche_start as i128) as usize; @@ -460,7 +462,7 @@ pub(crate) fn detect_variant_from_bytes<'a>( .filter(|x| x != untagged_variant) .nth(candidate_tag) .unwrap_or(*untagged_variant); - (variant.0, &variants[variant]) + (db.enum_data(e).variants[variant.0].0, &variants[variant]) } } } diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 5a21f41dca8..7b9f895bc73 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -115,7 +115,7 @@ fn resolve_doc_path_on_( AttrDefId::FieldId(it) => it.parent.resolver(db.upcast()), AttrDefId::AdtId(it) => it.resolver(db.upcast()), AttrDefId::FunctionId(it) => it.resolver(db.upcast()), - AttrDefId::EnumVariantId(it) => it.parent.resolver(db.upcast()), + AttrDefId::EnumVariantId(it) => it.resolver(db.upcast()), AttrDefId::StaticId(it) => it.resolver(db.upcast()), AttrDefId::ConstId(it) => it.resolver(db.upcast()), AttrDefId::TraitId(it) => it.resolver(db.upcast()), diff --git a/crates/hir/src/db.rs b/crates/hir/src/db.rs index 403a6c88ab0..a2492840cb7 100644 --- a/crates/hir/src/db.rs +++ b/crates/hir/src/db.rs @@ -6,8 +6,8 @@ pub use hir_def::db::{ AttrsQuery, BlockDefMapQuery, BlockItemTreeQueryQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, ConstVisibilityQuery, CrateDefMapQueryQuery, CrateLangItemsQuery, - CrateSupportsNoStdQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery, - EnumDataWithDiagnosticsQuery, ExprScopesQuery, ExternCrateDeclDataQuery, + CrateSupportsNoStdQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery, EnumVariantDataQuery, + EnumVariantDataWithDiagnosticsQuery, ExprScopesQuery, ExternCrateDeclDataQuery, FieldVisibilitiesQuery, FieldsAttrsQuery, FieldsAttrsSourceMapQuery, FileItemTreeQuery, FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery, ImplDataQuery, ImplDataWithDiagnosticsQuery, ImportMapQuery, InternAnonymousConstQuery, InternBlockQuery, @@ -19,7 +19,7 @@ pub use hir_def::db::{ MacroRulesDataQuery, ProcMacroDataQuery, StaticDataQuery, StructDataQuery, StructDataWithDiagnosticsQuery, TraitAliasDataQuery, TraitDataQuery, TraitDataWithDiagnosticsQuery, TypeAliasDataQuery, UnionDataQuery, - UnionDataWithDiagnosticsQuery, VariantsAttrsQuery, VariantsAttrsSourceMapQuery, + UnionDataWithDiagnosticsQuery, }; pub use hir_expand::db::{ AstIdMapQuery, DeclMacroExpanderQuery, ExpandDatabase, ExpandDatabaseStorage, diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs index fc4bbffdb83..887227bf4d0 100644 --- a/crates/hir/src/from_id.rs +++ b/crates/hir/src/from_id.rs @@ -93,13 +93,13 @@ impl From for GenericParamId { impl From for Variant { fn from(id: EnumVariantId) -> Self { - Variant { parent: id.parent.into(), id: id.local_id } + Variant { id } } } impl From for EnumVariantId { fn from(def: Variant) -> Self { - EnumVariantId { parent: def.parent.id, local_id: def.id } + def.id } } diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index 31cf8ba3364..d10884517f9 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs @@ -116,7 +116,7 @@ impl HasSource for Enum { impl HasSource for Variant { type Ast = ast::Variant; fn source(self, db: &dyn HirDatabase) -> Option> { - Some(self.parent.id.child_source(db.upcast()).map(|map| map[self.id].clone())) + Some(self.id.lookup(db.upcast()).source(db.upcast())) } } impl HasSource for Function { diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index c92939362ca..45aa3a05304 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -44,7 +44,7 @@ use hir_def::{ data::adt::VariantData, generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat}, - item_tree::ItemTreeNode, + item_tree::ItemTreeModItemNode, lang_item::LangItemTarget, layout::{self, ReprOptions, TargetDataLayout}, nameres::{self, diagnostics::DefDiagnostic}, @@ -54,9 +54,9 @@ use hir_def::{ src::HasSource as _, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, - ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, - Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, - TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, + ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, MacroExpander, + MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId, + TypeOrConstParamId, TypeParamId, UnionId, }; use hir_expand::{attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, MacroCallKind}; use hir_ty::{ @@ -375,9 +375,7 @@ impl ModuleDef { ModuleDef::Module(it) => it.id.into(), ModuleDef::Const(it) => it.id.into(), ModuleDef::Static(it) => it.id.into(), - ModuleDef::Variant(it) => { - EnumVariantId { parent: it.parent.into(), local_id: it.id }.into() - } + ModuleDef::Variant(it) => it.id.into(), ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(), }; @@ -586,10 +584,9 @@ impl Module { Adt::Enum(e) => { for v in e.variants(db) { acc.extend(ModuleDef::Variant(v).diagnostics(db)); - } - - for diag in db.enum_data_with_diagnostics(e.id).1.iter() { - emit_def_diagnostic(db, acc, diag); + for diag in db.enum_variant_data_with_diagnostics(v.id).1.iter() { + emit_def_diagnostic(db, acc, diag); + } } } } @@ -1084,7 +1081,7 @@ impl Field { let generic_def_id: GenericDefId = match self.parent { VariantDef::Struct(it) => it.id.into(), VariantDef::Union(it) => it.id.into(), - VariantDef::Variant(it) => it.parent.id.into(), + VariantDef::Variant(it) => it.id.into(), }; let substs = TyBuilder::placeholder_subst(db, generic_def_id); let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs); @@ -1224,7 +1221,7 @@ impl Enum { } pub fn variants(self, db: &dyn HirDatabase) -> Vec { - db.enum_data(self.id).variants.iter().map(|(id, _)| Variant { parent: self, id }).collect() + db.enum_data(self.id).variants.iter().map(|&(id, _)| Variant { id }).collect() } pub fn repr(self, db: &dyn HirDatabase) -> Option { @@ -1292,25 +1289,24 @@ impl From<&Variant> for DefWithBodyId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Variant { - pub(crate) parent: Enum, - pub(crate) id: LocalEnumVariantId, + pub(crate) id: EnumVariantId, } impl Variant { pub fn module(self, db: &dyn HirDatabase) -> Module { - self.parent.module(db) + Module { id: self.id.module(db.upcast()) } } - pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum { - self.parent + pub fn parent_enum(self, db: &dyn HirDatabase) -> Enum { + self.id.lookup(db.upcast()).parent.into() } pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type { - Type::from_value_def(db, EnumVariantId { parent: self.parent.id, local_id: self.id }) + Type::from_value_def(db, self.id) } pub fn name(self, db: &dyn HirDatabase) -> Name { - db.enum_data(self.parent.id).variants[self.id].name.clone() + db.enum_variant_data(self.id).name.clone() } pub fn fields(self, db: &dyn HirDatabase) -> Vec { @@ -1326,7 +1322,7 @@ impl Variant { } pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc { - db.enum_data(self.parent.id).variants[self.id].variant_data.clone() + db.enum_variant_data(self.id).variant_data.clone() } pub fn value(self, db: &dyn HirDatabase) -> Option { @@ -1342,7 +1338,11 @@ impl Variant { let parent_layout = parent_enum.layout(db)?; Ok(match &parent_layout.0.variants { layout::Variants::Multiple { variants, .. } => Layout( - Arc::new(variants[RustcEnumVariantIdx(self.id)].clone()), + { + let lookup = self.id.lookup(db.upcast()); + let rustc_enum_variant_idx = RustcEnumVariantIdx(lookup.index as usize); + Arc::new(variants[rustc_enum_variant_idx].clone()) + }, db.target_data_layout(parent_enum.krate(db).into()).unwrap(), ), _ => parent_layout, @@ -1547,7 +1547,7 @@ impl DefWithBody { DefWithBody::Function(it) => it.ret_type(db), DefWithBody::Static(it) => it.ty(db), DefWithBody::Const(it) => it.ty(db), - DefWithBody::Variant(it) => it.parent.variant_body_ty(db), + DefWithBody::Variant(it) => it.parent_enum(db).variant_body_ty(db), DefWithBody::InTypeConst(it) => Type::new_with_resolver_inner( db, &DefWithBodyId::from(it.id).resolver(db.upcast()), @@ -2828,7 +2828,7 @@ where ID: Lookup = dyn DefDatabase + 'db, Data = AssocItemLoc>, DEF: From, CTOR: FnOnce(DEF) -> AssocItem, - AST: ItemTreeNode, + AST: ItemTreeModItemNode, { match id.lookup(db.upcast()).container { ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))), diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index df8c1e904fe..cb04f98911e 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, diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs index e1101dd8236..28ac5940e69 100644 --- a/crates/hir/src/symbols.rs +++ b/crates/hir/src/symbols.rs @@ -262,9 +262,7 @@ impl<'a> SymbolCollector<'a> { DefWithBodyId::FunctionId(id) => Some(self.db.function_data(id).name.to_smol_str()), DefWithBodyId::StaticId(id) => Some(self.db.static_data(id).name.to_smol_str()), DefWithBodyId::ConstId(id) => Some(self.db.const_data(id).name.as_ref()?.to_smol_str()), - DefWithBodyId::VariantId(id) => { - Some(self.db.enum_data(id.parent).variants[id.local_id].name.to_smol_str()) - } + DefWithBodyId::VariantId(id) => Some(self.db.enum_variant_data(id).name.to_smol_str()), DefWithBodyId::InTypeConstId(_) => Some("in type const".into()), } } diff --git a/crates/ide-db/src/apply_change.rs b/crates/ide-db/src/apply_change.rs index 4f21f181d7c..3d973dfe10a 100644 --- a/crates/ide-db/src/apply_change.rs +++ b/crates/ide-db/src/apply_change.rs @@ -141,7 +141,8 @@ impl RootDatabase { hir::db::UnionDataQuery hir::db::UnionDataWithDiagnosticsQuery hir::db::EnumDataQuery - hir::db::EnumDataWithDiagnosticsQuery + hir::db::EnumVariantDataWithDiagnosticsQuery + hir::db::EnumVariantDataQuery hir::db::ImplDataQuery hir::db::ImplDataWithDiagnosticsQuery hir::db::TraitDataQuery @@ -158,9 +159,7 @@ impl RootDatabase { hir::db::BodyQuery hir::db::ExprScopesQuery hir::db::GenericParamsQuery - hir::db::VariantsAttrsQuery hir::db::FieldsAttrsQuery - hir::db::VariantsAttrsSourceMapQuery hir::db::FieldsAttrsSourceMapQuery hir::db::AttrsQuery hir::db::CrateLangItemsQuery diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs index ff26d862bfe..e1b6c13ba8e 100644 --- a/crates/ide-db/src/lib.rs +++ b/crates/ide-db/src/lib.rs @@ -222,7 +222,8 @@ impl RootDatabase { hir_db::UnionDataQuery hir_db::UnionDataWithDiagnosticsQuery hir_db::EnumDataQuery - hir_db::EnumDataWithDiagnosticsQuery + hir_db::EnumDataQuery + hir_db::EnumVariantDataWithDiagnosticsQuery hir_db::ImplDataQuery hir_db::ImplDataWithDiagnosticsQuery hir_db::TraitDataQuery @@ -239,9 +240,7 @@ impl RootDatabase { hir_db::BodyQuery hir_db::ExprScopesQuery hir_db::GenericParamsQuery - hir_db::VariantsAttrsQuery hir_db::FieldsAttrsQuery - hir_db::VariantsAttrsSourceMapQuery hir_db::FieldsAttrsSourceMapQuery hir_db::AttrsQuery hir_db::CrateLangItemsQuery diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 1c6157de559..19c2d3be16b 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -440,6 +440,12 @@ impl ast::Struct { } } +impl ast::Union { + pub fn kind(&self) -> StructKind { + StructKind::from_node(self) + } +} + impl ast::RecordExprField { pub fn for_field_name(field_name: &ast::NameRef) -> Option { let candidate = Self::for_name_ref(field_name)?;