diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index d2a975e9e6..85c0542ad3 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -24,12 +24,11 @@ use triomphe::Arc; use crate::{ db::DefDatabase, - item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeModItemNode}, + item_tree::{AttrOwner, Fields, ItemTreeNode}, lang_item::LangItem, nameres::{ModuleOrigin, ModuleSource}, src::{HasChildSource, HasSource}, - AdtId, AssocItemLoc, AttrDefId, GenericParamId, ItemLoc, LocalFieldId, Lookup, MacroId, - VariantId, + AdtId, AttrDefId, GenericParamId, ItemTreeLoc, LocalFieldId, Lookup, MacroId, VariantId, }; /// Desugared attributes of an item post `cfg_attr` expansion. @@ -356,12 +355,7 @@ impl AttrsWithOwner { AttrDefId::FieldId(it) => { return db.fields_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::EnumVariantId(it) => attrs_from_item_tree_loc(db, it), 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), @@ -370,15 +364,15 @@ impl AttrsWithOwner { AttrDefId::TraitId(it) => attrs_from_item_tree_loc(db, it), AttrDefId::TraitAliasId(it) => attrs_from_item_tree_loc(db, it), AttrDefId::MacroId(it) => match it { - MacroId::Macro2Id(it) => attrs_from_item_tree(db, it.lookup(db).id), - MacroId::MacroRulesId(it) => attrs_from_item_tree(db, it.lookup(db).id), - MacroId::ProcMacroId(it) => attrs_from_item_tree(db, it.lookup(db).id), + MacroId::Macro2Id(it) => attrs_from_item_tree_loc(db, it), + MacroId::MacroRulesId(it) => attrs_from_item_tree_loc(db, it), + MacroId::ProcMacroId(it) => attrs_from_item_tree_loc(db, it), }, AttrDefId::ImplId(it) => attrs_from_item_tree_loc(db, it), - AttrDefId::ConstId(it) => attrs_from_item_tree_assoc(db, it), - AttrDefId::StaticId(it) => attrs_from_item_tree_assoc(db, it), - AttrDefId::FunctionId(it) => attrs_from_item_tree_assoc(db, it), - AttrDefId::TypeAliasId(it) => attrs_from_item_tree_assoc(db, it), + AttrDefId::ConstId(it) => attrs_from_item_tree_loc(db, it), + AttrDefId::StaticId(it) => attrs_from_item_tree_loc(db, it), + AttrDefId::FunctionId(it) => attrs_from_item_tree_loc(db, it), + AttrDefId::TypeAliasId(it) => attrs_from_item_tree_loc(db, it), AttrDefId::GenericParamId(it) => match it { GenericParamId::ConstParamId(it) => { let src = it.parent().child_source(db); @@ -603,29 +597,14 @@ fn any_has_attrs<'db>( id.lookup(db).source(db).map(ast::AnyHasAttrs::new) } -fn attrs_from_item_tree( - db: &dyn DefDatabase, - id: ItemTreeId, +fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>( + db: &(dyn DefDatabase + 'db), + lookup: impl Lookup = dyn DefDatabase + 'db, Data = impl ItemTreeLoc>, ) -> RawAttrs { + let id = lookup.lookup(db).item_tree_id(); 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: ItemTreeModItemNode>( - db: &(dyn DefDatabase + 'db), - lookup: impl Lookup = dyn DefDatabase + 'db, Data = ItemLoc>, -) -> RawAttrs { - let id = lookup.lookup(db).id; - attrs_from_item_tree(db, id) -} - -fn attrs_from_item_tree_assoc<'db, N: ItemTreeModItemNode>( - db: &(dyn DefDatabase + 'db), - lookup: impl Lookup = dyn DefDatabase + 'db, Data = AssocItemLoc>, -) -> RawAttrs { - let id = lookup.lookup(db).id; - attrs_from_item_tree(db, id) + let attr_owner = N::attr_owner(id.value); + tree.raw_attrs(attr_owner).clone() } pub(crate) fn fields_attrs_source_map( diff --git a/crates/hir-def/src/child_by_source.rs b/crates/hir-def/src/child_by_source.rs index b3bb3355f1..5efa3e8d9e 100644 --- a/crates/hir-def/src/child_by_source.rs +++ b/crates/hir-def/src/child_by_source.rs @@ -9,12 +9,16 @@ use hir_expand::{attrs::collect_attrs, HirFileId}; use crate::{ db::DefDatabase, - dyn_map::{keys, DynMap}, + dyn_map::{ + keys::{self, Key}, + DynMap, + }, item_scope::ItemScope, + item_tree::ItemTreeNode, nameres::DefMap, src::{HasChildSource, HasSource}, - AdtId, AssocItemId, DefWithBodyId, EnumId, ExternCrateId, FieldId, ImplId, Lookup, MacroId, - ModuleDefId, ModuleId, TraitId, UseId, VariantId, + AdtId, AssocItemId, DefWithBodyId, EnumId, FieldId, ImplId, ItemTreeLoc, Lookup, MacroId, + ModuleDefId, ModuleId, TraitId, VariantId, }; pub trait ChildBySource { @@ -57,24 +61,9 @@ impl ChildBySource for ImplId { fn add_assoc_item(db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId, item: AssocItemId) { match item { - AssocItemId::FunctionId(func) => { - let loc = func.lookup(db); - if loc.id.file_id() == file_id { - res[keys::FUNCTION].insert(loc.source(db).value, func) - } - } - AssocItemId::ConstId(konst) => { - let loc = konst.lookup(db); - if loc.id.file_id() == file_id { - res[keys::CONST].insert(loc.source(db).value, konst) - } - } - AssocItemId::TypeAliasId(ty) => { - let loc = ty.lookup(db); - if loc.id.file_id() == file_id { - res[keys::TYPE_ALIAS].insert(loc.source(db).value, ty) - } - } + AssocItemId::FunctionId(func) => insert_item_loc(db, res, file_id, func, keys::FUNCTION), + AssocItemId::ConstId(konst) => insert_item_loc(db, res, file_id, konst, keys::CONST), + AssocItemId::TypeAliasId(ty) => insert_item_loc(db, res, file_id, ty, keys::TYPE_ALIAS), } } @@ -89,15 +78,12 @@ impl ChildBySource for ModuleId { impl ChildBySource for ItemScope { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { self.declarations().for_each(|item| add_module_def(db, res, file_id, item)); - self.impls().for_each(|imp| add_impl(db, res, file_id, imp)); - self.extern_crate_decls().for_each(|ext| add_extern_crate(db, res, file_id, ext)); - self.use_decls().for_each(|ext| add_use(db, res, file_id, ext)); - self.unnamed_consts(db).for_each(|konst| { - let loc = konst.lookup(db); - if loc.id.file_id() == file_id { - res[keys::CONST].insert(loc.source(db).value, konst); - } - }); + self.impls().for_each(|imp| insert_item_loc(db, res, file_id, imp, keys::IMPL)); + self.extern_crate_decls() + .for_each(|ext| insert_item_loc(db, res, file_id, ext, keys::EXTERN_CRATE)); + self.use_decls().for_each(|ext| insert_item_loc(db, res, file_id, ext, keys::USE)); + self.unnamed_consts(db) + .for_each(|konst| insert_item_loc(db, res, file_id, konst, keys::CONST)); self.attr_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each( |(ast_id, call_id)| { res[keys::ATTR_MACRO_CALL].insert(ast_id.to_node(db.upcast()), call_id); @@ -141,16 +127,22 @@ impl ChildBySource for ItemScope { }}; } match item { - ModuleDefId::FunctionId(id) => insert!(map[keys::FUNCTION].insert(id)), - ModuleDefId::ConstId(id) => insert!(map[keys::CONST].insert(id)), - ModuleDefId::StaticId(id) => insert!(map[keys::STATIC].insert(id)), - ModuleDefId::TypeAliasId(id) => insert!(map[keys::TYPE_ALIAS].insert(id)), - ModuleDefId::TraitId(id) => insert!(map[keys::TRAIT].insert(id)), - ModuleDefId::TraitAliasId(id) => insert!(map[keys::TRAIT_ALIAS].insert(id)), + ModuleDefId::FunctionId(id) => { + insert_item_loc(db, map, file_id, id, keys::FUNCTION) + } + ModuleDefId::ConstId(id) => insert_item_loc(db, map, file_id, id, keys::CONST), + ModuleDefId::TypeAliasId(id) => { + insert_item_loc(db, map, file_id, id, keys::TYPE_ALIAS) + } + ModuleDefId::StaticId(id) => insert_item_loc(db, map, file_id, id, keys::STATIC), + ModuleDefId::TraitId(id) => insert_item_loc(db, map, file_id, id, keys::TRAIT), + ModuleDefId::TraitAliasId(id) => { + insert_item_loc(db, map, file_id, id, keys::TRAIT_ALIAS) + } ModuleDefId::AdtId(adt) => match adt { - AdtId::StructId(id) => insert!(map[keys::STRUCT].insert(id)), - AdtId::UnionId(id) => insert!(map[keys::UNION].insert(id)), - AdtId::EnumId(id) => insert!(map[keys::ENUM].insert(id)), + AdtId::StructId(id) => insert_item_loc(db, map, file_id, id, keys::STRUCT), + AdtId::UnionId(id) => insert_item_loc(db, map, file_id, id, keys::UNION), + AdtId::EnumId(id) => insert_item_loc(db, map, file_id, id, keys::ENUM), }, ModuleDefId::MacroId(id) => match id { MacroId::Macro2Id(id) => insert!(map[keys::MACRO2].insert(id)), @@ -162,29 +154,6 @@ impl ChildBySource for ItemScope { | ModuleDefId::BuiltinType(_) => (), } } - fn add_impl(db: &dyn DefDatabase, map: &mut DynMap, file_id: HirFileId, imp: ImplId) { - let loc = imp.lookup(db); - if loc.id.file_id() == file_id { - map[keys::IMPL].insert(loc.source(db).value, imp) - } - } - fn add_extern_crate( - db: &dyn DefDatabase, - map: &mut DynMap, - file_id: HirFileId, - ext: ExternCrateId, - ) { - let loc = ext.lookup(db); - if loc.id.file_id() == file_id { - map[keys::EXTERN_CRATE].insert(loc.source(db).value, ext) - } - } - fn add_use(db: &dyn DefDatabase, map: &mut DynMap, file_id: HirFileId, ext: UseId) { - let loc = ext.lookup(db); - if loc.id.file_id() == file_id { - map[keys::USE].insert(loc.source(db).value, ext) - } - } } } @@ -237,3 +206,21 @@ impl ChildBySource for DefWithBodyId { } } } + +fn insert_item_loc( + db: &dyn DefDatabase, + res: &mut DynMap, + file_id: HirFileId, + id: ID, + key: Key, +) where + ID: for<'db> Lookup = dyn DefDatabase + 'db, Data = Data> + 'static, + Data: ItemTreeLoc, + N: ItemTreeNode, + N::Source: 'static, +{ + let loc = id.lookup(db); + if loc.item_tree_id().file_id() == file_id { + res[key].insert(loc.source(db).value, id) + } +} diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index 8dce7fdb4d..0edd5e6168 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -509,47 +509,36 @@ impl GenericParams { } fn file_id_and_params_of( - def: GenericDefId, db: &dyn DefDatabase, + def: GenericDefId, ) -> (HirFileId, Option) { match def { - GenericDefId::FunctionId(it) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - GenericDefId::AdtId(AdtId::StructId(it)) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - GenericDefId::AdtId(AdtId::UnionId(it)) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - GenericDefId::AdtId(AdtId::EnumId(it)) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - GenericDefId::TraitId(it) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - GenericDefId::TraitAliasId(it) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - GenericDefId::TypeAliasId(it) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } - GenericDefId::ImplId(it) => { - let src = it.lookup(db).source(db); - (src.file_id, src.value.generic_param_list()) - } + GenericDefId::FunctionId(it) => file_id_and_params_of_item_loc(db, it), + GenericDefId::TypeAliasId(it) => file_id_and_params_of_item_loc(db, it), + GenericDefId::ConstId(_) => (FileId::BOGUS.into(), None), + GenericDefId::AdtId(AdtId::StructId(it)) => file_id_and_params_of_item_loc(db, it), + GenericDefId::AdtId(AdtId::UnionId(it)) => file_id_and_params_of_item_loc(db, it), + GenericDefId::AdtId(AdtId::EnumId(it)) => file_id_and_params_of_item_loc(db, it), + GenericDefId::TraitId(it) => file_id_and_params_of_item_loc(db, it), + GenericDefId::TraitAliasId(it) => file_id_and_params_of_item_loc(db, it), + GenericDefId::ImplId(it) => file_id_and_params_of_item_loc(db, it), // We won't be using this ID anyway - GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => (FileId::BOGUS.into(), None), + GenericDefId::EnumVariantId(_) => (FileId::BOGUS.into(), None), } } +fn file_id_and_params_of_item_loc( + db: &dyn DefDatabase, + def: impl for<'db> Lookup = dyn DefDatabase + 'db, Data = Loc>, +) -> (HirFileId, Option) +where + Loc: HasSource, + Loc::Value: HasGenericParams, +{ + let src = def.lookup(db).source(db); + (src.file_id, src.value.generic_param_list()) +} + impl HasChildSource for GenericDefId { type Value = Either; fn child_source( @@ -559,7 +548,7 @@ impl HasChildSource for GenericDefId { let generic_params = db.generic_params(*self); let mut idx_iter = generic_params.type_or_consts.iter().map(|(idx, _)| idx); - let (file_id, generic_params_list) = file_id_and_params_of(*self, db); + let (file_id, generic_params_list) = file_id_and_params_of(db, *self); let mut params = ArenaMap::default(); @@ -598,7 +587,7 @@ impl HasChildSource for GenericDefId { let generic_params = db.generic_params(*self); let idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx); - let (file_id, generic_params_list) = file_id_and_params_of(*self, db); + let (file_id, generic_params_list) = file_id_and_params_of(db, *self); let mut params = ArenaMap::default(); @@ -614,7 +603,7 @@ impl HasChildSource for GenericDefId { impl ChildBySource for GenericDefId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { - let (gfile_id, generic_params_list) = file_id_and_params_of(*self, db); + let (gfile_id, generic_params_list) = file_id_and_params_of(db, *self); if gfile_id != file_id { return; } diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 27c5f14b7d..96b606ec1d 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -337,20 +337,15 @@ from_attrs!( LifetimeParamData(Idx), ); -/// Trait implemented by all item nodes in the item tree. -pub trait ItemTreeModItemNode: Clone { - type Source: AstIdNode + Into; +/// Trait implemented by all nodes in the item tree. +pub trait ItemTreeNode: Clone { + type Source: AstIdNode; fn ast_id(&self) -> FileAstId; /// Looks up an instance of `Self` in an item tree. fn lookup(tree: &ItemTree, index: Idx) -> &Self; - - /// Downcasts a `ModItem` to a `FileItemTreeId` specific to this type. - fn id_from_mod_item(mod_item: ModItem) -> Option>; - - /// Upcasts a `FileItemTreeId` to a generic `ModItem`. - fn id_to_mod_item(id: FileItemTreeId) -> ModItem; + fn attr_owner(id: FileItemTreeId) -> AttrOwner; } pub struct FileItemTreeId(Idx); @@ -495,7 +490,7 @@ macro_rules! mod_items { )+ $( - impl ItemTreeModItemNode for $typ { + impl ItemTreeNode for $typ { type Source = $ast; fn ast_id(&self) -> FileAstId { @@ -506,15 +501,8 @@ macro_rules! mod_items { &tree.data().$fld[index] } - fn id_from_mod_item(mod_item: ModItem) -> Option> { - match mod_item { - ModItem::$typ(id) => Some(id), - _ => None, - } - } - - fn id_to_mod_item(id: FileItemTreeId) -> ModItem { - ModItem::$typ(id) + fn attr_owner(id: FileItemTreeId) -> AttrOwner { + AttrOwner::ModItem(ModItem::$typ(id)) } } @@ -578,17 +566,26 @@ 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()] +impl ItemTreeNode for Variant { + type Source = ast::Variant; + + fn ast_id(&self) -> FileAstId { + self.ast_id + } + + fn lookup(tree: &ItemTree, index: Idx) -> &Self { + &tree.data().variants[index] + } + + fn attr_owner(id: FileItemTreeId) -> AttrOwner { + AttrOwner::Variant(id) } } @@ -1027,7 +1024,7 @@ impl AssocItem { } } -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Variant { pub name: Name, pub fields: Fields, diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index b500f56b6c..1cc8158909 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) } @@ -267,7 +267,7 @@ impl<'a> Ctx<'a> { if let Some(data) = self.lower_variant(&variant) { let idx = self.data().variants.alloc(data); self.add_attrs( - FileItemTreeId(idx).into(), + id(idx).into(), RawAttrs::new(self.db.upcast(), &variant, self.span_map()), ); } diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index ef4f538785..df1f61ae5f 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -98,8 +98,8 @@ use crate::{ data::adt::VariantData, db::DefDatabase, item_tree::{ - Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeModItemNode, Macro2, - MacroRules, Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant, + Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules, + Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant, }, }; @@ -212,28 +212,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 } } -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); @@ -241,34 +241,41 @@ 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 } } -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); } } +pub trait ItemTreeLoc { + type Container; + type Id; + fn item_tree_id(&self) -> ItemTreeId; + fn container(&self) -> Self::Container; +} + macro_rules! impl_intern { ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => { impl_intern_key!($id); @@ -276,25 +283,44 @@ macro_rules! impl_intern { }; } +macro_rules! impl_loc { + ($loc:ident, $id:ident: $id_ty:ident, $container:ident: $container_type:ident) => { + impl ItemTreeLoc for $loc { + type Container = $container_type; + type Id = $id_ty; + fn item_tree_id(&self) -> ItemTreeId { + self.$id + } + fn container(&self) -> Self::Container { + self.$container + } + } + }; +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct FunctionId(salsa::InternId); type FunctionLoc = AssocItemLoc; impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function); +impl_loc!(FunctionLoc, id: Function, container: ItemContainerId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct StructId(salsa::InternId); type StructLoc = ItemLoc; impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct); +impl_loc!(StructLoc, id: Struct, container: ModuleId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct UnionId(salsa::InternId); pub type UnionLoc = ItemLoc; impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union); +impl_loc!(UnionLoc, id: Union, container: ModuleId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct EnumId(salsa::InternId); pub type EnumLoc = ItemLoc; impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum); +impl_loc!(EnumLoc, id: Enum, container: ModuleId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct EnumVariantId(salsa::InternId); @@ -306,6 +332,7 @@ pub struct EnumVariantLoc { pub index: u32, } impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_enum_variant); +impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct FieldId { @@ -328,46 +355,55 @@ pub struct TupleFieldId { pub struct ConstId(salsa::InternId); type ConstLoc = AssocItemLoc; impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const); +impl_loc!(ConstLoc, id: Const, container: ItemContainerId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StaticId(salsa::InternId); pub type StaticLoc = AssocItemLoc; impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static); +impl_loc!(StaticLoc, id: Static, container: ItemContainerId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TraitId(salsa::InternId); pub type TraitLoc = ItemLoc; impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait); +impl_loc!(TraitLoc, id: Trait, container: ModuleId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TraitAliasId(salsa::InternId); pub type TraitAliasLoc = ItemLoc; impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias); +impl_loc!(TraitAliasLoc, id: TraitAlias, container: ModuleId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TypeAliasId(salsa::InternId); type TypeAliasLoc = AssocItemLoc; impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias); +impl_loc!(TypeAliasLoc, id: TypeAlias, container: ItemContainerId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] pub struct ImplId(salsa::InternId); type ImplLoc = ItemLoc; impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); +impl_loc!(ImplLoc, id: Impl, container: ModuleId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] pub struct UseId(salsa::InternId); type UseLoc = ItemLoc; impl_intern!(UseId, UseLoc, intern_use, lookup_intern_use); +impl_loc!(UseLoc, id: Use, container: ModuleId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] pub struct ExternCrateId(salsa::InternId); type ExternCrateLoc = ItemLoc; impl_intern!(ExternCrateId, ExternCrateLoc, intern_extern_crate, lookup_intern_extern_crate); +impl_loc!(ExternCrateLoc, id: ExternCrate, container: ModuleId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] pub struct ExternBlockId(salsa::InternId); type ExternBlockLoc = ItemLoc; impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_extern_block); +impl_loc!(ExternBlockLoc, id: ExternBlock, container: ModuleId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum MacroExpander { @@ -389,6 +425,7 @@ pub struct Macro2Loc { pub edition: Edition, } impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2); +impl_loc!(Macro2Loc, id: Macro2, container: ModuleId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] pub struct MacroRulesId(salsa::InternId); @@ -401,6 +438,7 @@ pub struct MacroRulesLoc { pub edition: Edition, } impl_intern!(MacroRulesId, MacroRulesLoc, intern_macro_rules, lookup_intern_macro_rules); +impl_loc!(MacroRulesLoc, id: MacroRules, container: ModuleId); bitflags::bitflags! { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -421,6 +459,7 @@ pub struct ProcMacroLoc { pub edition: Edition, } impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_macro); +impl_loc!(ProcMacroLoc, id: Function, container: CrateRootModuleId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] pub struct BlockId(salsa::InternId); @@ -986,44 +1025,92 @@ impl VariantId { } pub trait HasModule { + /// Returns the enclosing module this thing is defined within. fn module(&self, db: &dyn DefDatabase) -> ModuleId; -} - -impl HasModule for ItemContainerId { - fn module(&self, db: &dyn DefDatabase) -> ModuleId { - match *self { - ItemContainerId::ModuleId(it) => it, - ItemContainerId::ImplId(it) => it.lookup(db).container, - ItemContainerId::TraitId(it) => it.lookup(db).container, - ItemContainerId::ExternBlockId(it) => it.lookup(db).container, - } - } -} - -impl HasModule for AssocItemLoc { + /// Returns the crate this thing is defined within. #[inline] - fn module(&self, db: &dyn DefDatabase) -> ModuleId { - self.container.module(db) + #[doc(alias = "crate")] + fn krate(&self, db: &dyn DefDatabase) -> CrateId { + self.module(db).krate } } -impl HasModule for AdtId { - fn module(&self, db: &dyn DefDatabase) -> ModuleId { - match self { - AdtId::StructId(it) => it.lookup(db).container, - AdtId::UnionId(it) => it.lookup(db).container, - AdtId::EnumId(it) => it.lookup(db).container, - } - } -} +// In theory this impl should work out for us, but rustc thinks it collides with all the other +// manual impls that do not have a ModuleId container... +// impl HasModule for ItemId +// where +// N: ItemTreeNode, +// ItemId: for<'db> Lookup = dyn DefDatabase + 'db, Data = Data> + Copy, +// Data: ItemTreeLoc, +// { +// #[inline] +// fn module(&self, db: &dyn DefDatabase) -> ModuleId { +// self.lookup(db).container() +// } +// } -impl HasModule for EnumId { +impl HasModule for ItemId +where + N: ItemTreeNode, + ItemId: for<'db> Lookup = dyn DefDatabase + 'db, Data = ItemLoc> + Copy, +{ #[inline] fn module(&self, db: &dyn DefDatabase) -> ModuleId { self.lookup(db).container } } +// Technically this does not overlap with the above, but rustc currently forbids this, hence why we +// need to write the 3 impls manually instead +// impl HasModule for ItemId +// where +// N: ItemTreeModItemNode, +// ItemId: for<'db> Lookup = dyn DefDatabase + 'db, Data = AssocItemLoc> + Copy, +// { +// #[inline] +// fn module(&self, db: &dyn DefDatabase) -> ModuleId { +// self.lookup(db).container.module(db) +// } +// } + +// region: manual-assoc-has-module-impls +#[inline] +fn module_for_assoc_item_loc<'db>( + db: &(dyn 'db + DefDatabase), + id: impl Lookup = dyn DefDatabase + 'db, Data = AssocItemLoc>, +) -> ModuleId { + id.lookup(db).container.module(db) +} + +impl HasModule for FunctionId { + #[inline] + fn module(&self, db: &dyn DefDatabase) -> ModuleId { + module_for_assoc_item_loc(db, *self) + } +} + +impl HasModule for ConstId { + #[inline] + fn module(&self, db: &dyn DefDatabase) -> ModuleId { + module_for_assoc_item_loc(db, *self) + } +} + +impl HasModule for StaticId { + #[inline] + fn module(&self, db: &dyn DefDatabase) -> ModuleId { + module_for_assoc_item_loc(db, *self) + } +} + +impl HasModule for TypeAliasId { + #[inline] + fn module(&self, db: &dyn DefDatabase) -> ModuleId { + module_for_assoc_item_loc(db, *self) + } +} +// endregion: manual-assoc-has-module-impls + impl HasModule for EnumVariantId { #[inline] fn module(&self, db: &dyn DefDatabase) -> ModuleId { @@ -1031,46 +1118,81 @@ impl HasModule for EnumVariantId { } } -impl HasModule for ExternCrateId { +impl HasModule for MacroRulesId { #[inline] fn module(&self, db: &dyn DefDatabase) -> ModuleId { self.lookup(db).container } } +impl HasModule for Macro2Id { + #[inline] + fn module(&self, db: &dyn DefDatabase) -> ModuleId { + self.lookup(db).container + } +} + +impl HasModule for ProcMacroId { + #[inline] + fn module(&self, db: &dyn DefDatabase) -> ModuleId { + self.lookup(db).container.into() + } +} + +impl HasModule for ItemContainerId { + fn module(&self, db: &dyn DefDatabase) -> ModuleId { + match *self { + ItemContainerId::ModuleId(it) => it, + ItemContainerId::ImplId(it) => it.module(db), + ItemContainerId::TraitId(it) => it.module(db), + ItemContainerId::ExternBlockId(it) => it.module(db), + } + } +} + +impl HasModule for AdtId { + fn module(&self, db: &dyn DefDatabase) -> ModuleId { + match *self { + AdtId::StructId(it) => it.module(db), + AdtId::UnionId(it) => it.module(db), + AdtId::EnumId(it) => it.module(db), + } + } +} + impl HasModule for VariantId { fn module(&self, db: &dyn DefDatabase) -> ModuleId { - match self { - VariantId::EnumVariantId(it) => it.lookup(db).parent.module(db), - VariantId::StructId(it) => it.lookup(db).container, - VariantId::UnionId(it) => it.lookup(db).container, + match *self { + VariantId::EnumVariantId(it) => it.module(db), + VariantId::StructId(it) => it.module(db), + VariantId::UnionId(it) => it.module(db), } } } impl HasModule for MacroId { fn module(&self, db: &dyn DefDatabase) -> ModuleId { - match self { - MacroId::MacroRulesId(it) => it.lookup(db).container, - MacroId::Macro2Id(it) => it.lookup(db).container, - MacroId::ProcMacroId(it) => it.lookup(db).container.into(), + match *self { + MacroId::MacroRulesId(it) => it.module(db), + MacroId::Macro2Id(it) => it.module(db), + MacroId::ProcMacroId(it) => it.module(db), } } } impl HasModule for TypeOwnerId { fn module(&self, db: &dyn DefDatabase) -> ModuleId { - match self { - TypeOwnerId::FunctionId(it) => it.lookup(db).module(db), - TypeOwnerId::StaticId(it) => it.lookup(db).module(db), - TypeOwnerId::ConstId(it) => it.lookup(db).module(db), - TypeOwnerId::InTypeConstId(it) => it.lookup(db).owner.module(db), + match *self { + TypeOwnerId::FunctionId(it) => it.module(db), + TypeOwnerId::StaticId(it) => it.module(db), + TypeOwnerId::ConstId(it) => it.module(db), TypeOwnerId::AdtId(it) => it.module(db), - TypeOwnerId::TraitId(it) => it.lookup(db).container, - 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.lookup(db).parent.module(db), + TypeOwnerId::TraitId(it) => it.module(db), + TypeOwnerId::TraitAliasId(it) => it.module(db), + TypeOwnerId::TypeAliasId(it) => it.module(db), + TypeOwnerId::ImplId(it) => it.module(db), + TypeOwnerId::EnumVariantId(it) => it.module(db), + TypeOwnerId::InTypeConstId(it) => it.lookup(db).owner.module(db), } } } @@ -1078,10 +1200,10 @@ impl HasModule for TypeOwnerId { impl HasModule for DefWithBodyId { fn module(&self, db: &dyn DefDatabase) -> ModuleId { match self { - 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.lookup(db).parent.module(db), + DefWithBodyId::FunctionId(it) => it.module(db), + DefWithBodyId::StaticId(it) => it.module(db), + DefWithBodyId::ConstId(it) => it.module(db), + DefWithBodyId::VariantId(it) => it.module(db), DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db), } } @@ -1090,32 +1212,18 @@ impl HasModule for DefWithBodyId { impl HasModule for GenericDefId { fn module(&self, db: &dyn DefDatabase) -> ModuleId { match self { - GenericDefId::FunctionId(it) => it.lookup(db).module(db), + GenericDefId::FunctionId(it) => it.module(db), GenericDefId::AdtId(it) => it.module(db), - GenericDefId::TraitId(it) => it.lookup(db).container, - 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.lookup(db).parent.lookup(db).container, - GenericDefId::ConstId(it) => it.lookup(db).module(db), + GenericDefId::TraitId(it) => it.module(db), + GenericDefId::TraitAliasId(it) => it.module(db), + GenericDefId::TypeAliasId(it) => it.module(db), + GenericDefId::ImplId(it) => it.module(db), + GenericDefId::EnumVariantId(it) => it.module(db), + GenericDefId::ConstId(it) => it.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 - } -} - impl ModuleDefId { /// Returns the module containing `self` (or `self`, if `self` is itself a module). /// @@ -1123,14 +1231,14 @@ impl ModuleDefId { pub fn module(&self, db: &dyn DefDatabase) -> Option { Some(match self { ModuleDefId::ModuleId(id) => *id, - ModuleDefId::FunctionId(id) => id.lookup(db).module(db), + ModuleDefId::FunctionId(id) => id.module(db), ModuleDefId::AdtId(id) => id.module(db), - 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, - ModuleDefId::TraitAliasId(id) => id.lookup(db).container, - ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db), + ModuleDefId::EnumVariantId(id) => id.module(db), + ModuleDefId::ConstId(id) => id.module(db), + ModuleDefId::StaticId(id) => id.module(db), + ModuleDefId::TraitId(id) => id.module(db), + ModuleDefId::TraitAliasId(id) => id.module(db), + ModuleDefId::TypeAliasId(id) => id.module(db), ModuleDefId::MacroId(id) => id.module(db), ModuleDefId::BuiltinType(_) => return None, }) @@ -1139,31 +1247,28 @@ impl ModuleDefId { impl AttrDefId { pub fn krate(&self, db: &dyn DefDatabase) -> CrateId { - match self { + match *self { AttrDefId::ModuleId(it) => it.krate, - 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.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, - AttrDefId::TraitAliasId(it) => it.lookup(db).container.krate, - AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate, - AttrDefId::ImplId(it) => it.lookup(db).container.krate, - AttrDefId::ExternBlockId(it) => it.lookup(db).container.krate, - AttrDefId::GenericParamId(it) => { - match it { - GenericParamId::TypeParamId(it) => it.parent(), - GenericParamId::ConstParamId(it) => it.parent(), - GenericParamId::LifetimeParamId(it) => it.parent, - } - .module(db) - .krate + AttrDefId::FieldId(it) => it.parent.krate(db), + AttrDefId::AdtId(it) => it.krate(db), + AttrDefId::FunctionId(it) => it.krate(db), + AttrDefId::EnumVariantId(it) => it.krate(db), + AttrDefId::StaticId(it) => it.krate(db), + AttrDefId::ConstId(it) => it.krate(db), + AttrDefId::TraitId(it) => it.krate(db), + AttrDefId::TraitAliasId(it) => it.krate(db), + AttrDefId::TypeAliasId(it) => it.krate(db), + AttrDefId::ImplId(it) => it.krate(db), + AttrDefId::ExternBlockId(it) => it.krate(db), + AttrDefId::GenericParamId(it) => match it { + GenericParamId::TypeParamId(it) => it.parent(), + GenericParamId::ConstParamId(it) => it.parent(), + GenericParamId::LifetimeParamId(it) => it.parent, } - AttrDefId::MacroId(it) => it.module(db).krate, - AttrDefId::ExternCrateId(it) => it.lookup(db).container.krate, - AttrDefId::UseId(it) => it.lookup(db).container.krate, + .krate(db), + AttrDefId::MacroId(it) => it.krate(db), + AttrDefId::ExternCrateId(it) => it.krate(db), + AttrDefId::UseId(it) => it.krate(db), } } } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 49d59cf9ad..21cc28f1b3 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -33,8 +33,8 @@ use crate::{ db::DefDatabase, item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports}, item_tree::{ - self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, - ItemTreeModItemNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, + self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, + Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, }, macro_call_as_call_id, macro_call_as_call_id_with_eager, nameres::{ diff --git a/crates/hir-def/src/src.rs b/crates/hir-def/src/src.rs index 9bd8c8d221..d820456b92 100644 --- a/crates/hir-def/src/src.rs +++ b/crates/hir-def/src/src.rs @@ -4,91 +4,29 @@ use hir_expand::InFile; use la_arena::ArenaMap; use syntax::ast; -use crate::{ - db::DefDatabase, item_tree::ItemTreeModItemNode, AssocItemLoc, EnumVariantLoc, ItemLoc, Lookup, - Macro2Loc, MacroRulesLoc, ProcMacroLoc, UseId, -}; +use crate::{db::DefDatabase, item_tree::ItemTreeNode, ItemTreeLoc, Lookup, UseId}; pub trait HasSource { type Value; fn source(&self, db: &dyn DefDatabase) -> InFile; } -impl HasSource for AssocItemLoc { - type Value = N::Source; - - 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 ItemLoc { - type Value = N::Source; - - 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 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; +impl HasSource for T +where + T: ItemTreeLoc, + T::Id: ItemTreeNode, +{ + type Value = ::Source; 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]; + let id = self.item_tree_id(); + let file_id = id.file_id(); + let tree = id.item_tree(db); + let ast_id_map = db.ast_id_map(file_id); + let root = db.parse_or_expand(file_id); + let node = &tree[id.value]; - InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id()).to_node(&root)) - } -} - -impl HasSource for MacroRulesLoc { - type Value = ast::MacroRules; - - 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 ProcMacroLoc { - type Value = ast::Fn; - - 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)) + InFile::new(file_id, ast_id_map.get(node.ast_id()).to_node(&root)) } } diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 2327c8df1b..a57149ea60 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -814,9 +814,8 @@ impl HirDisplay for Ty { // Don't count Sized but count when it absent // (i.e. when explicit ?Sized bound is set). - let default_sized = SizedByDefault::Sized { - anchor: func.lookup(db.upcast()).module(db.upcast()).krate(), - }; + let default_sized = + SizedByDefault::Sized { anchor: func.krate(db.upcast()) }; let sized_bounds = bounds .skip_binders() .iter() @@ -1025,7 +1024,7 @@ impl HirDisplay for Ty { let data = (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); let bounds = data.substitute(Interner, ¶meters); - let krate = func.lookup(db.upcast()).module(db.upcast()).krate(); + let krate = func.krate(db.upcast()); write_bounds_like_dyn_trait_with_prefix( f, "impl", @@ -1191,7 +1190,7 @@ impl HirDisplay for Ty { let data = (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); let bounds = data.substitute(Interner, &opaque_ty.substitution); - let krate = func.lookup(db.upcast()).module(db.upcast()).krate(); + let krate = func.krate(db.upcast()); write_bounds_like_dyn_trait_with_prefix( f, "impl", diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 386a03d93f..142b954639 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -1225,7 +1225,7 @@ impl<'a> TyLoweringContext<'a> { .collect(); if !ctx.unsized_types.borrow().contains(&self_ty) { - let krate = func.lookup(ctx.db.upcast()).module(ctx.db.upcast()).krate(); + let krate = func.krate(ctx.db.upcast()); let sized_trait = ctx .db .lang_item(krate, LangItem::Sized) @@ -1824,11 +1824,10 @@ impl CallableDefId { pub fn krate(self, db: &dyn HirDatabase) -> CrateId { let db = db.upcast(); match self { - CallableDefId::FunctionId(f) => f.lookup(db).module(db), - CallableDefId::StructId(s) => s.lookup(db).container, - CallableDefId::EnumVariantId(e) => e.module(db), + CallableDefId::FunctionId(f) => f.krate(db), + CallableDefId::StructId(s) => s.krate(db), + CallableDefId::EnumVariantId(e) => e.krate(db), } - .krate() } } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 60e829b0a7..e5a113fe7f 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::ItemTreeModItemNode, + item_tree::ItemTreeNode, lang_item::LangItemTarget, layout::{self, ReprOptions, TargetDataLayout}, nameres::{self, diagnostics::DefDiagnostic}, @@ -1768,7 +1768,7 @@ pub struct Function { impl Function { pub fn module(self, db: &dyn HirDatabase) -> Module { - self.id.lookup(db.upcast()).module(db.upcast()).into() + self.id.module(db.upcast()).into() } pub fn name(self, db: &dyn HirDatabase) -> Name { @@ -1909,8 +1909,7 @@ impl Function { { return None; } - let loc = self.id.lookup(db.upcast()); - let def_map = db.crate_def_map(loc.krate(db).into()); + let def_map = db.crate_def_map(HasModule::krate(&self.id, db.upcast())); def_map.fn_as_proc_macro(self.id).map(|id| Macro { id: id.into() }) } @@ -2119,7 +2118,7 @@ pub struct Const { impl Const { pub fn module(self, db: &dyn HirDatabase) -> Module { - Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } + Module { id: self.id.module(db.upcast()) } } pub fn name(self, db: &dyn HirDatabase) -> Option { @@ -2174,7 +2173,7 @@ pub struct Static { impl Static { pub fn module(self, db: &dyn HirDatabase) -> Module { - Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } + Module { id: self.id.module(db.upcast()) } } pub fn name(self, db: &dyn HirDatabase) -> Name { @@ -2293,7 +2292,7 @@ impl TypeAlias { } pub fn module(self, db: &dyn HirDatabase) -> Module { - Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } + Module { id: self.id.module(db.upcast()) } } pub fn type_ref(self, db: &dyn HirDatabase) -> Option { @@ -2516,11 +2515,13 @@ pub enum AssocItem { Const(Const), TypeAlias(TypeAlias), } + #[derive(Debug, Clone)] pub enum AssocItemContainer { Trait(Trait), Impl(Impl), } + pub trait AsAssocItem { fn as_assoc_item(self, db: &dyn HirDatabase) -> Option; } @@ -2530,16 +2531,19 @@ impl AsAssocItem for Function { as_assoc_item(db, AssocItem::Function, self.id) } } + impl AsAssocItem for Const { fn as_assoc_item(self, db: &dyn HirDatabase) -> Option { as_assoc_item(db, AssocItem::Const, self.id) } } + impl AsAssocItem for TypeAlias { fn as_assoc_item(self, db: &dyn HirDatabase) -> Option { as_assoc_item(db, AssocItem::TypeAlias, self.id) } } + impl AsAssocItem for ModuleDef { fn as_assoc_item(self, db: &dyn HirDatabase) -> Option { match self { @@ -2550,6 +2554,7 @@ impl AsAssocItem for ModuleDef { } } } + impl AsAssocItem for DefWithBody { fn as_assoc_item(self, db: &dyn HirDatabase) -> Option { match self { @@ -2560,16 +2565,15 @@ impl AsAssocItem for DefWithBody { } } -fn as_assoc_item<'db, ID, DEF, CTOR, AST>( +fn as_assoc_item<'db, ID, DEF, LOC>( db: &(dyn HirDatabase + 'db), - ctor: CTOR, + ctor: impl FnOnce(DEF) -> AssocItem, id: ID, ) -> Option where - ID: Lookup = dyn DefDatabase + 'db, Data = AssocItemLoc>, + ID: Lookup = dyn DefDatabase + 'db, Data = AssocItemLoc>, DEF: From, - CTOR: FnOnce(DEF) -> AssocItem, - AST: ItemTreeModItemNode, + LOC: ItemTreeNode, { match id.lookup(db.upcast()).container { ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))), @@ -2609,27 +2613,34 @@ impl AssocItem { } } - pub fn containing_trait(self, db: &dyn HirDatabase) -> Option { + pub fn container_trait(self, db: &dyn HirDatabase) -> Option { match self.container(db) { AssocItemContainer::Trait(t) => Some(t), _ => None, } } - pub fn containing_trait_impl(self, db: &dyn HirDatabase) -> Option { + pub fn implemented_trait(self, db: &dyn HirDatabase) -> Option { match self.container(db) { AssocItemContainer::Impl(i) => i.trait_(db), _ => None, } } - pub fn containing_trait_or_trait_impl(self, db: &dyn HirDatabase) -> Option { + pub fn container_or_implemented_trait(self, db: &dyn HirDatabase) -> Option { match self.container(db) { AssocItemContainer::Trait(t) => Some(t), AssocItemContainer::Impl(i) => i.trait_(db), } } + pub fn implementing_ty(self, db: &dyn HirDatabase) -> Option { + match self.container(db) { + AssocItemContainer::Impl(i) => Some(i.self_ty(db)), + _ => None, + } + } + pub fn as_function(self) -> Option { match self { Self::Function(v) => Some(v), @@ -3321,7 +3332,7 @@ impl Impl { } pub fn items(self, db: &dyn HirDatabase) -> Vec { - db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect() + db.impl_data(self.id).items.iter().map(|&it| it.into()).collect() } pub fn is_negative(self, db: &dyn HirDatabase) -> bool { @@ -3677,7 +3688,7 @@ impl Type { .and_then(|it| { let into_future_fn = it.as_function()?; let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?; - let into_future_trait = assoc_item.containing_trait_or_trait_impl(db)?; + let into_future_trait = assoc_item.container_or_implemented_trait(db)?; Some(into_future_trait.id) }) .or_else(|| { diff --git a/crates/ide-assists/src/handlers/convert_bool_then.rs b/crates/ide-assists/src/handlers/convert_bool_then.rs index d231708c55..61b7b41217 100644 --- a/crates/ide-assists/src/handlers/convert_bool_then.rs +++ b/crates/ide-assists/src/handlers/convert_bool_then.rs @@ -163,9 +163,8 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_> return None; } let assoc = func.as_assoc_item(ctx.sema.db)?; - match assoc.container(ctx.sema.db) { - hir::AssocItemContainer::Impl(impl_) if impl_.self_ty(ctx.sema.db).is_bool() => {} - _ => return None, + if !assoc.implementing_ty(ctx.sema.db)?.is_bool() { + return None; } let target = mcall.syntax().text_range(); diff --git a/crates/ide-assists/src/handlers/generate_documentation_template.rs b/crates/ide-assists/src/handlers/generate_documentation_template.rs index f720391cc8..38b24fd19c 100644 --- a/crates/ide-assists/src/handlers/generate_documentation_template.rs +++ b/crates/ide-assists/src/handlers/generate_documentation_template.rs @@ -364,7 +364,7 @@ fn is_in_trait_impl(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> bool { ctx.sema .to_def(ast_func) .and_then(|hir_func| hir_func.as_assoc_item(ctx.db())) - .and_then(|assoc_item| assoc_item.containing_trait_impl(ctx.db())) + .and_then(|assoc_item| assoc_item.implemented_trait(ctx.db())) .is_some() } @@ -373,7 +373,7 @@ fn is_in_trait_def(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> bool { ctx.sema .to_def(ast_func) .and_then(|hir_func| hir_func.as_assoc_item(ctx.db())) - .and_then(|assoc_item| assoc_item.containing_trait(ctx.db())) + .and_then(|assoc_item| assoc_item.container_trait(ctx.db())) .is_some() } diff --git a/crates/ide-assists/src/handlers/into_to_qualified_from.rs b/crates/ide-assists/src/handlers/into_to_qualified_from.rs index f7da88b2c1..dee74afcbe 100644 --- a/crates/ide-assists/src/handlers/into_to_qualified_from.rs +++ b/crates/ide-assists/src/handlers/into_to_qualified_from.rs @@ -48,7 +48,7 @@ pub(crate) fn into_to_qualified_from(acc: &mut Assists, ctx: &AssistContext<'_>) let fnc = sema.resolve_method_call(&method_call)?; let scope = sema.scope(method_call.syntax())?; // Check if the method call refers to Into trait. - if fnc.as_assoc_item(db)?.containing_trait_impl(db)? + if fnc.as_assoc_item(db)?.implemented_trait(db)? == FamousDefs(sema, scope.krate()).core_convert_Into()? { let type_call = sema.type_of_expr(&method_call.clone().into())?; diff --git a/crates/ide-assists/src/handlers/qualify_path.rs b/crates/ide-assists/src/handlers/qualify_path.rs index 0864871849..63a09ce2e9 100644 --- a/crates/ide-assists/src/handlers/qualify_path.rs +++ b/crates/ide-assists/src/handlers/qualify_path.rs @@ -203,7 +203,7 @@ fn item_as_trait(db: &RootDatabase, item: hir::ItemInNs) -> Option { match item_module_def { hir::ModuleDef::Trait(trait_) => Some(trait_), - _ => item_module_def.as_assoc_item(db)?.containing_trait(db), + _ => item_module_def.as_assoc_item(db)?.container_trait(db), } } diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index 548466d8de..2ed080a834 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -112,7 +112,7 @@ impl<'a> RenderContext<'a> { }; is_assoc_deprecated || assoc - .containing_trait_or_trait_impl(db) + .container_or_implemented_trait(db) .map(|trait_| self.is_deprecated(trait_)) .unwrap_or(false) } diff --git a/crates/ide-completion/src/render/const_.rs b/crates/ide-completion/src/render/const_.rs index a2bfac994f..0d24882156 100644 --- a/crates/ide-completion/src/render/const_.rs +++ b/crates/ide-completion/src/render/const_.rs @@ -23,7 +23,7 @@ fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option .set_relevance(ctx.completion_relevance()); if let Some(actm) = const_.as_assoc_item(db) { - if let Some(trt) = actm.containing_trait_or_trait_impl(db) { + if let Some(trt) = actm.container_or_implemented_trait(db) { item.trait_name(trt.name(db).to_smol_str()); } } diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs index f3ac06c131..27186a2b7f 100644 --- a/crates/ide-completion/src/render/function.rs +++ b/crates/ide-completion/src/render/function.rs @@ -75,7 +75,7 @@ fn render( let ret_type = func.ret_type(db); let assoc_item = func.as_assoc_item(db); - let trait_ = assoc_item.and_then(|trait_| trait_.containing_trait_or_trait_impl(db)); + let trait_ = assoc_item.and_then(|trait_| trait_.container_or_implemented_trait(db)); let is_op_method = trait_.map_or(false, |trait_| completion.is_ops_trait(trait_)); let is_item_from_notable_trait = @@ -145,7 +145,7 @@ fn render( } None => { if let Some(actm) = assoc_item { - if let Some(trt) = actm.containing_trait_or_trait_impl(db) { + if let Some(trt) = actm.container_or_implemented_trait(db) { item.trait_name(trt.name(db).to_smol_str()); } } diff --git a/crates/ide-completion/src/render/type_alias.rs b/crates/ide-completion/src/render/type_alias.rs index b192309e93..8f80793dd7 100644 --- a/crates/ide-completion/src/render/type_alias.rs +++ b/crates/ide-completion/src/render/type_alias.rs @@ -47,7 +47,7 @@ fn render( .set_relevance(ctx.completion_relevance()); if let Some(actm) = type_alias.as_assoc_item(db) { - if let Some(trt) = actm.containing_trait_or_trait_impl(db) { + if let Some(trt) = actm.container_or_implemented_trait(db) { item.trait_name(trt.name(db).to_smol_str()); } } diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 81f2f87d96..d95d94ec72 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -206,7 +206,7 @@ impl Definition { // docs are missing, for assoc items of trait impls try to fall back to the docs of the // original item of the trait let assoc = self.as_assoc_item(db)?; - let trait_ = assoc.containing_trait_impl(db)?; + let trait_ = assoc.implemented_trait(db)?; let name = Some(assoc.name(db)?); let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?; item.docs(db) diff --git a/crates/ide-db/src/imports/import_assets.rs b/crates/ide-db/src/imports/import_assets.rs index b7b10c08eb..a71d8e9002 100644 --- a/crates/ide-db/src/imports/import_assets.rs +++ b/crates/ide-db/src/imports/import_assets.rs @@ -529,7 +529,7 @@ fn trait_applicable_items( return None; } - let assoc_item_trait = assoc.containing_trait(db)?; + let assoc_item_trait = assoc.container_trait(db)?; if related_traits.contains(&assoc_item_trait) { return None; } @@ -550,8 +550,7 @@ fn trait_applicable_items( None, |assoc| { if required_assoc_items.contains(&assoc) { - let located_trait = - assoc.containing_trait(db).filter(|&it| scope_filter(it))?; + let located_trait = assoc.container_trait(db).filter(|&it| scope_filter(it))?; let trait_item = ItemInNs::from(ModuleDef::from(located_trait)); let import_path = trait_import_paths .entry(trait_item) @@ -576,8 +575,7 @@ fn trait_applicable_items( |function| { let assoc = function.as_assoc_item(db)?; if required_assoc_items.contains(&assoc) { - let located_trait = - assoc.containing_trait(db).filter(|&it| scope_filter(it))?; + let located_trait = assoc.container_trait(db).filter(|&it| scope_filter(it))?; let trait_item = ItemInNs::from(ModuleDef::from(located_trait)); let import_path = trait_import_paths .entry(trait_item) diff --git a/crates/ide-db/src/traits.rs b/crates/ide-db/src/traits.rs index bbdfd81d65..ee7c448bb8 100644 --- a/crates/ide-db/src/traits.rs +++ b/crates/ide-db/src/traits.rs @@ -75,7 +75,7 @@ pub fn get_missing_assoc_items( pub(crate) fn convert_to_def_in_trait(db: &dyn HirDatabase, def: Definition) -> Definition { (|| { let assoc = def.as_assoc_item(db)?; - let trait_ = assoc.containing_trait_impl(db)?; + let trait_ = assoc.implemented_trait(db)?; assoc_item_of_trait(db, assoc, trait_) })() .unwrap_or(def) diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index ea54734d34..dbe6a5507c 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs @@ -668,7 +668,7 @@ fn get_assoc_item_fragment(db: &dyn HirDatabase, assoc_item: hir::AssocItem) -> Some(match assoc_item { AssocItem::Function(function) => { let is_trait_method = - function.as_assoc_item(db).and_then(|assoc| assoc.containing_trait(db)).is_some(); + function.as_assoc_item(db).and_then(|assoc| assoc.container_trait(db)).is_some(); // This distinction may get more complicated when specialization is available. // Rustdoc makes this decision based on whether a method 'has defaultness'. // Currently this is only the case for provided trait methods. diff --git a/crates/ide/src/goto_declaration.rs b/crates/ide/src/goto_declaration.rs index fae1007435..fab62e95d1 100644 --- a/crates/ide/src/goto_declaration.rs +++ b/crates/ide/src/goto_declaration.rs @@ -61,7 +61,7 @@ pub(crate) fn goto_declaration( _ => None, }?; - let trait_ = assoc.containing_trait_impl(db)?; + let trait_ = assoc.implemented_trait(db)?; let name = Some(assoc.name(db)?); let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?; item.try_to_nav(db) diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 4fed1f9158..88255d222e 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -182,11 +182,7 @@ fn try_filter_trait_item_definition( match assoc { AssocItem::Function(..) => None, AssocItem::Const(..) | AssocItem::TypeAlias(..) => { - let imp = match assoc.container(db) { - hir::AssocItemContainer::Impl(imp) => imp, - _ => return None, - }; - let trait_ = imp.trait_(db)?; + let trait_ = assoc.implemented_trait(db)?; let name = def.name(db)?; let discri_value = discriminant(&assoc); trait_ diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs index c1a4a7b1fc..8a12cbaccc 100644 --- a/crates/ide/src/goto_implementation.rs +++ b/crates/ide/src/goto_implementation.rs @@ -60,13 +60,13 @@ pub(crate) fn goto_implementation( Definition::Function(f) => { let assoc = f.as_assoc_item(sema.db)?; let name = assoc.name(sema.db)?; - let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?; + let trait_ = assoc.container_or_implemented_trait(sema.db)?; impls_for_trait_item(&sema, trait_, name) } Definition::Const(c) => { let assoc = c.as_assoc_item(sema.db)?; let name = assoc.name(sema.db)?; - let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?; + let trait_ = assoc.container_or_implemented_trait(sema.db)?; impls_for_trait_item(&sema, trait_, name) } _ => return None, diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index 40b9a5de19..ae107a9604 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -442,8 +442,7 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option { .for_each(|name| format_to!(path, "{}::", name.display(db))); // This probably belongs to canonical_path? if let Some(assoc_item) = def.as_assoc_item(db) { - if let hir::AssocItemContainer::Impl(imp) = assoc_item.container(db) { - let ty = imp.self_ty(db); + if let Some(ty) = assoc_item.implementing_ty(db) { if let Some(adt) = ty.as_adt() { let name = adt.name(db); let mut ty_args = ty.generic_parameters(db).peekable(); diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index d686652bb3..e7c1b4497e 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs @@ -559,7 +559,7 @@ fn highlight_method_call( } if func .as_assoc_item(sema.db) - .and_then(|it| it.containing_trait_or_trait_impl(sema.db)) + .and_then(|it| it.container_or_implemented_trait(sema.db)) .is_some() { h |= HlMod::Trait;