Auto merge of #16525 - Veykril:item-loc, r=Veykril

Abstract more over ItemTreeLoc-like structs

Allows reducing some code duplication by using functions generic over said structs. The diff isn't negative due to me adding some additional impls for completeness.
This commit is contained in:
bors 2024-02-10 10:47:37 +00:00
commit 1ef7a2329b
28 changed files with 409 additions and 413 deletions

View file

@ -24,12 +24,11 @@ use triomphe::Arc;
use crate::{ use crate::{
db::DefDatabase, db::DefDatabase,
item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeModItemNode}, item_tree::{AttrOwner, Fields, ItemTreeNode},
lang_item::LangItem, lang_item::LangItem,
nameres::{ModuleOrigin, ModuleSource}, nameres::{ModuleOrigin, ModuleSource},
src::{HasChildSource, HasSource}, src::{HasChildSource, HasSource},
AdtId, AssocItemLoc, AttrDefId, GenericParamId, ItemLoc, LocalFieldId, Lookup, MacroId, AdtId, AttrDefId, GenericParamId, ItemTreeLoc, LocalFieldId, Lookup, MacroId, VariantId,
VariantId,
}; };
/// Desugared attributes of an item post `cfg_attr` expansion. /// Desugared attributes of an item post `cfg_attr` expansion.
@ -356,12 +355,7 @@ impl AttrsWithOwner {
AttrDefId::FieldId(it) => { AttrDefId::FieldId(it) => {
return db.fields_attrs(it.parent)[it.local_id].clone(); return db.fields_attrs(it.parent)[it.local_id].clone();
} }
// FIXME: DRY this up AttrDefId::EnumVariantId(it) => attrs_from_item_tree_loc(db, it),
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 { AttrDefId::AdtId(it) => match it {
AdtId::StructId(it) => attrs_from_item_tree_loc(db, it), AdtId::StructId(it) => attrs_from_item_tree_loc(db, it),
AdtId::EnumId(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::TraitId(it) => attrs_from_item_tree_loc(db, it),
AttrDefId::TraitAliasId(it) => attrs_from_item_tree_loc(db, it), AttrDefId::TraitAliasId(it) => attrs_from_item_tree_loc(db, it),
AttrDefId::MacroId(it) => match it { AttrDefId::MacroId(it) => match it {
MacroId::Macro2Id(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(db, it.lookup(db).id), MacroId::MacroRulesId(it) => attrs_from_item_tree_loc(db, it),
MacroId::ProcMacroId(it) => attrs_from_item_tree(db, it.lookup(db).id), MacroId::ProcMacroId(it) => attrs_from_item_tree_loc(db, it),
}, },
AttrDefId::ImplId(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::ConstId(it) => attrs_from_item_tree_loc(db, it),
AttrDefId::StaticId(it) => attrs_from_item_tree_assoc(db, it), AttrDefId::StaticId(it) => attrs_from_item_tree_loc(db, it),
AttrDefId::FunctionId(it) => attrs_from_item_tree_assoc(db, it), AttrDefId::FunctionId(it) => attrs_from_item_tree_loc(db, it),
AttrDefId::TypeAliasId(it) => attrs_from_item_tree_assoc(db, it), AttrDefId::TypeAliasId(it) => attrs_from_item_tree_loc(db, it),
AttrDefId::GenericParamId(it) => match it { AttrDefId::GenericParamId(it) => match it {
GenericParamId::ConstParamId(it) => { GenericParamId::ConstParamId(it) => {
let src = it.parent().child_source(db); 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) id.lookup(db).source(db).map(ast::AnyHasAttrs::new)
} }
fn attrs_from_item_tree<N: ItemTreeModItemNode>( fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>(
db: &dyn DefDatabase, db: &(dyn DefDatabase + 'db),
id: ItemTreeId<N>, lookup: impl Lookup<Database<'db> = dyn DefDatabase + 'db, Data = impl ItemTreeLoc<Id = N>>,
) -> RawAttrs { ) -> RawAttrs {
let id = lookup.lookup(db).item_tree_id();
let tree = id.item_tree(db); let tree = id.item_tree(db);
let mod_item = N::id_to_mod_item(id.value); let attr_owner = N::attr_owner(id.value);
tree.raw_attrs(mod_item.into()).clone() tree.raw_attrs(attr_owner).clone()
}
fn attrs_from_item_tree_loc<'db, N: ItemTreeModItemNode>(
db: &(dyn DefDatabase + 'db),
lookup: impl Lookup<Database<'db> = dyn DefDatabase + 'db, Data = ItemLoc<N>>,
) -> 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<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<N>>,
) -> RawAttrs {
let id = lookup.lookup(db).id;
attrs_from_item_tree(db, id)
} }
pub(crate) fn fields_attrs_source_map( pub(crate) fn fields_attrs_source_map(

View file

@ -9,12 +9,16 @@ use hir_expand::{attrs::collect_attrs, HirFileId};
use crate::{ use crate::{
db::DefDatabase, db::DefDatabase,
dyn_map::{keys, DynMap}, dyn_map::{
keys::{self, Key},
DynMap,
},
item_scope::ItemScope, item_scope::ItemScope,
item_tree::ItemTreeNode,
nameres::DefMap, nameres::DefMap,
src::{HasChildSource, HasSource}, src::{HasChildSource, HasSource},
AdtId, AssocItemId, DefWithBodyId, EnumId, ExternCrateId, FieldId, ImplId, Lookup, MacroId, AdtId, AssocItemId, DefWithBodyId, EnumId, FieldId, ImplId, ItemTreeLoc, Lookup, MacroId,
ModuleDefId, ModuleId, TraitId, UseId, VariantId, ModuleDefId, ModuleId, TraitId, VariantId,
}; };
pub trait ChildBySource { 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) { fn add_assoc_item(db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId, item: AssocItemId) {
match item { match item {
AssocItemId::FunctionId(func) => { AssocItemId::FunctionId(func) => insert_item_loc(db, res, file_id, func, keys::FUNCTION),
let loc = func.lookup(db); AssocItemId::ConstId(konst) => insert_item_loc(db, res, file_id, konst, keys::CONST),
if loc.id.file_id() == file_id { AssocItemId::TypeAliasId(ty) => insert_item_loc(db, res, file_id, ty, keys::TYPE_ALIAS),
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)
}
}
} }
} }
@ -89,15 +78,12 @@ impl ChildBySource for ModuleId {
impl ChildBySource for ItemScope { impl ChildBySource for ItemScope {
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { 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.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.impls().for_each(|imp| insert_item_loc(db, res, file_id, imp, keys::IMPL));
self.extern_crate_decls().for_each(|ext| add_extern_crate(db, res, file_id, ext)); self.extern_crate_decls()
self.use_decls().for_each(|ext| add_use(db, res, file_id, ext)); .for_each(|ext| insert_item_loc(db, res, file_id, ext, keys::EXTERN_CRATE));
self.unnamed_consts(db).for_each(|konst| { self.use_decls().for_each(|ext| insert_item_loc(db, res, file_id, ext, keys::USE));
let loc = konst.lookup(db); self.unnamed_consts(db)
if loc.id.file_id() == file_id { .for_each(|konst| insert_item_loc(db, res, file_id, konst, keys::CONST));
res[keys::CONST].insert(loc.source(db).value, konst);
}
});
self.attr_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each( self.attr_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each(
|(ast_id, call_id)| { |(ast_id, call_id)| {
res[keys::ATTR_MACRO_CALL].insert(ast_id.to_node(db.upcast()), 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 { match item {
ModuleDefId::FunctionId(id) => insert!(map[keys::FUNCTION].insert(id)), ModuleDefId::FunctionId(id) => {
ModuleDefId::ConstId(id) => insert!(map[keys::CONST].insert(id)), insert_item_loc(db, map, file_id, id, keys::FUNCTION)
ModuleDefId::StaticId(id) => insert!(map[keys::STATIC].insert(id)), }
ModuleDefId::TypeAliasId(id) => insert!(map[keys::TYPE_ALIAS].insert(id)), ModuleDefId::ConstId(id) => insert_item_loc(db, map, file_id, id, keys::CONST),
ModuleDefId::TraitId(id) => insert!(map[keys::TRAIT].insert(id)), ModuleDefId::TypeAliasId(id) => {
ModuleDefId::TraitAliasId(id) => insert!(map[keys::TRAIT_ALIAS].insert(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 { ModuleDefId::AdtId(adt) => match adt {
AdtId::StructId(id) => insert!(map[keys::STRUCT].insert(id)), AdtId::StructId(id) => insert_item_loc(db, map, file_id, id, keys::STRUCT),
AdtId::UnionId(id) => insert!(map[keys::UNION].insert(id)), AdtId::UnionId(id) => insert_item_loc(db, map, file_id, id, keys::UNION),
AdtId::EnumId(id) => insert!(map[keys::ENUM].insert(id)), AdtId::EnumId(id) => insert_item_loc(db, map, file_id, id, keys::ENUM),
}, },
ModuleDefId::MacroId(id) => match id { ModuleDefId::MacroId(id) => match id {
MacroId::Macro2Id(id) => insert!(map[keys::MACRO2].insert(id)), MacroId::Macro2Id(id) => insert!(map[keys::MACRO2].insert(id)),
@ -162,29 +154,6 @@ impl ChildBySource for ItemScope {
| ModuleDefId::BuiltinType(_) => (), | 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<ID, N, Data>(
db: &dyn DefDatabase,
res: &mut DynMap,
file_id: HirFileId,
id: ID,
key: Key<N::Source, ID>,
) where
ID: for<'db> Lookup<Database<'db> = dyn DefDatabase + 'db, Data = Data> + 'static,
Data: ItemTreeLoc<Id = N>,
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)
}
}

View file

@ -509,47 +509,36 @@ impl GenericParams {
} }
fn file_id_and_params_of( fn file_id_and_params_of(
def: GenericDefId,
db: &dyn DefDatabase, db: &dyn DefDatabase,
def: GenericDefId,
) -> (HirFileId, Option<ast::GenericParamList>) { ) -> (HirFileId, Option<ast::GenericParamList>) {
match def { match def {
GenericDefId::FunctionId(it) => { GenericDefId::FunctionId(it) => file_id_and_params_of_item_loc(db, it),
let src = it.lookup(db).source(db); GenericDefId::TypeAliasId(it) => file_id_and_params_of_item_loc(db, it),
(src.file_id, src.value.generic_param_list()) GenericDefId::ConstId(_) => (FileId::BOGUS.into(), None),
} GenericDefId::AdtId(AdtId::StructId(it)) => file_id_and_params_of_item_loc(db, it),
GenericDefId::AdtId(AdtId::StructId(it)) => { GenericDefId::AdtId(AdtId::UnionId(it)) => file_id_and_params_of_item_loc(db, it),
let src = it.lookup(db).source(db); GenericDefId::AdtId(AdtId::EnumId(it)) => file_id_and_params_of_item_loc(db, it),
(src.file_id, src.value.generic_param_list()) 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::AdtId(AdtId::UnionId(it)) => { GenericDefId::ImplId(it) => file_id_and_params_of_item_loc(db, 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())
}
// We won't be using this ID anyway // 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<Loc>(
db: &dyn DefDatabase,
def: impl for<'db> Lookup<Database<'db> = dyn DefDatabase + 'db, Data = Loc>,
) -> (HirFileId, Option<ast::GenericParamList>)
where
Loc: HasSource,
Loc::Value: HasGenericParams,
{
let src = def.lookup(db).source(db);
(src.file_id, src.value.generic_param_list())
}
impl HasChildSource<LocalTypeOrConstParamId> for GenericDefId { impl HasChildSource<LocalTypeOrConstParamId> for GenericDefId {
type Value = Either<ast::TypeOrConstParam, ast::TraitOrAlias>; type Value = Either<ast::TypeOrConstParam, ast::TraitOrAlias>;
fn child_source( fn child_source(
@ -559,7 +548,7 @@ impl HasChildSource<LocalTypeOrConstParamId> for GenericDefId {
let generic_params = db.generic_params(*self); let generic_params = db.generic_params(*self);
let mut idx_iter = generic_params.type_or_consts.iter().map(|(idx, _)| idx); 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(); let mut params = ArenaMap::default();
@ -598,7 +587,7 @@ impl HasChildSource<LocalLifetimeParamId> for GenericDefId {
let generic_params = db.generic_params(*self); let generic_params = db.generic_params(*self);
let idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx); 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(); let mut params = ArenaMap::default();
@ -614,7 +603,7 @@ impl HasChildSource<LocalLifetimeParamId> for GenericDefId {
impl ChildBySource for GenericDefId { impl ChildBySource for GenericDefId {
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { 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 { if gfile_id != file_id {
return; return;
} }

View file

@ -337,20 +337,15 @@ from_attrs!(
LifetimeParamData(Idx<LifetimeParamData>), LifetimeParamData(Idx<LifetimeParamData>),
); );
/// Trait implemented by all item nodes in the item tree. /// Trait implemented by all nodes in the item tree.
pub trait ItemTreeModItemNode: Clone { pub trait ItemTreeNode: Clone {
type Source: AstIdNode + Into<ast::Item>; type Source: AstIdNode;
fn ast_id(&self) -> FileAstId<Self::Source>; fn ast_id(&self) -> FileAstId<Self::Source>;
/// Looks up an instance of `Self` in an item tree. /// Looks up an instance of `Self` in an item tree.
fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self; fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self;
fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner;
/// Downcasts a `ModItem` to a `FileItemTreeId` specific to this type.
fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>>;
/// Upcasts a `FileItemTreeId` to a generic `ModItem`.
fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem;
} }
pub struct FileItemTreeId<N>(Idx<N>); pub struct FileItemTreeId<N>(Idx<N>);
@ -495,7 +490,7 @@ macro_rules! mod_items {
)+ )+
$( $(
impl ItemTreeModItemNode for $typ { impl ItemTreeNode for $typ {
type Source = $ast; type Source = $ast;
fn ast_id(&self) -> FileAstId<Self::Source> { fn ast_id(&self) -> FileAstId<Self::Source> {
@ -506,15 +501,8 @@ macro_rules! mod_items {
&tree.data().$fld[index] &tree.data().$fld[index]
} }
fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>> { fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner {
match mod_item { AttrOwner::ModItem(ModItem::$typ(id))
ModItem::$typ(id) => Some(id),
_ => None,
}
}
fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem {
ModItem::$typ(id)
} }
} }
@ -578,17 +566,26 @@ impl Index<RawVisibilityId> for ItemTree {
} }
} }
impl<N: ItemTreeModItemNode> Index<FileItemTreeId<N>> for ItemTree { impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
type Output = N; type Output = N;
fn index(&self, id: FileItemTreeId<N>) -> &N { fn index(&self, id: FileItemTreeId<N>) -> &N {
N::lookup(self, id.index()) N::lookup(self, id.index())
} }
} }
impl Index<FileItemTreeId<Variant>> for ItemTree { impl ItemTreeNode for Variant {
type Output = Variant; type Source = ast::Variant;
fn index(&self, id: FileItemTreeId<Variant>) -> &Variant {
&self[id.index()] fn ast_id(&self) -> FileAstId<Self::Source> {
self.ast_id
}
fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self {
&tree.data().variants[index]
}
fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner {
AttrOwner::Variant(id)
} }
} }
@ -1027,7 +1024,7 @@ impl AssocItem {
} }
} }
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct Variant { pub struct Variant {
pub name: Name, pub name: Name,
pub fields: Fields, pub fields: Fields,

View file

@ -13,7 +13,7 @@ use crate::{
use super::*; use super::*;
fn id<N: ItemTreeModItemNode>(index: Idx<N>) -> FileItemTreeId<N> { fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> {
FileItemTreeId(index) FileItemTreeId(index)
} }
@ -267,7 +267,7 @@ impl<'a> Ctx<'a> {
if let Some(data) = self.lower_variant(&variant) { if let Some(data) = self.lower_variant(&variant) {
let idx = self.data().variants.alloc(data); let idx = self.data().variants.alloc(data);
self.add_attrs( self.add_attrs(
FileItemTreeId(idx).into(), id(idx).into(),
RawAttrs::new(self.db.upcast(), &variant, self.span_map()), RawAttrs::new(self.db.upcast(), &variant, self.span_map()),
); );
} }

View file

@ -98,8 +98,8 @@ use crate::{
data::adt::VariantData, data::adt::VariantData,
db::DefDatabase, db::DefDatabase,
item_tree::{ item_tree::{
Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeModItemNode, Macro2, Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules,
MacroRules, Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant, Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant,
}, },
}; };
@ -212,28 +212,28 @@ impl ModuleId {
pub type LocalModuleId = Idx<nameres::ModuleData>; pub type LocalModuleId = Idx<nameres::ModuleData>;
#[derive(Debug)] #[derive(Debug)]
pub struct ItemLoc<N: ItemTreeModItemNode> { pub struct ItemLoc<N: ItemTreeNode> {
pub container: ModuleId, pub container: ModuleId,
pub id: ItemTreeId<N>, pub id: ItemTreeId<N>,
} }
impl<N: ItemTreeModItemNode> Clone for ItemLoc<N> { impl<N: ItemTreeNode> Clone for ItemLoc<N> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
} }
impl<N: ItemTreeModItemNode> Copy for ItemLoc<N> {} impl<N: ItemTreeNode> Copy for ItemLoc<N> {}
impl<N: ItemTreeModItemNode> PartialEq for ItemLoc<N> { impl<N: ItemTreeNode> PartialEq for ItemLoc<N> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.container == other.container && self.id == other.id self.container == other.container && self.id == other.id
} }
} }
impl<N: ItemTreeModItemNode> Eq for ItemLoc<N> {} impl<N: ItemTreeNode> Eq for ItemLoc<N> {}
impl<N: ItemTreeModItemNode> Hash for ItemLoc<N> { impl<N: ItemTreeNode> Hash for ItemLoc<N> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.container.hash(state); self.container.hash(state);
self.id.hash(state); self.id.hash(state);
@ -241,34 +241,41 @@ impl<N: ItemTreeModItemNode> Hash for ItemLoc<N> {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct AssocItemLoc<N: ItemTreeModItemNode> { pub struct AssocItemLoc<N: ItemTreeNode> {
pub container: ItemContainerId, pub container: ItemContainerId,
pub id: ItemTreeId<N>, pub id: ItemTreeId<N>,
} }
impl<N: ItemTreeModItemNode> Clone for AssocItemLoc<N> { impl<N: ItemTreeNode> Clone for AssocItemLoc<N> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
} }
impl<N: ItemTreeModItemNode> Copy for AssocItemLoc<N> {} impl<N: ItemTreeNode> Copy for AssocItemLoc<N> {}
impl<N: ItemTreeModItemNode> PartialEq for AssocItemLoc<N> { impl<N: ItemTreeNode> PartialEq for AssocItemLoc<N> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.container == other.container && self.id == other.id self.container == other.container && self.id == other.id
} }
} }
impl<N: ItemTreeModItemNode> Eq for AssocItemLoc<N> {} impl<N: ItemTreeNode> Eq for AssocItemLoc<N> {}
impl<N: ItemTreeModItemNode> Hash for AssocItemLoc<N> { impl<N: ItemTreeNode> Hash for AssocItemLoc<N> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.container.hash(state); self.container.hash(state);
self.id.hash(state); self.id.hash(state);
} }
} }
pub trait ItemTreeLoc {
type Container;
type Id;
fn item_tree_id(&self) -> ItemTreeId<Self::Id>;
fn container(&self) -> Self::Container;
}
macro_rules! impl_intern { macro_rules! impl_intern {
($id:ident, $loc:ident, $intern:ident, $lookup:ident) => { ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => {
impl_intern_key!($id); 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> {
self.$id
}
fn container(&self) -> Self::Container {
self.$container
}
}
};
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FunctionId(salsa::InternId); pub struct FunctionId(salsa::InternId);
type FunctionLoc = AssocItemLoc<Function>; type FunctionLoc = AssocItemLoc<Function>;
impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function); 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct StructId(salsa::InternId); pub struct StructId(salsa::InternId);
type StructLoc = ItemLoc<Struct>; type StructLoc = ItemLoc<Struct>;
impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct); 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct UnionId(salsa::InternId); pub struct UnionId(salsa::InternId);
pub type UnionLoc = ItemLoc<Union>; pub type UnionLoc = ItemLoc<Union>;
impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union); 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct EnumId(salsa::InternId); pub struct EnumId(salsa::InternId);
pub type EnumLoc = ItemLoc<Enum>; pub type EnumLoc = ItemLoc<Enum>;
impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum); impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
impl_loc!(EnumLoc, id: Enum, container: ModuleId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EnumVariantId(salsa::InternId); pub struct EnumVariantId(salsa::InternId);
@ -306,6 +332,7 @@ pub struct EnumVariantLoc {
pub index: u32, pub index: u32,
} }
impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_enum_variant); 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FieldId { pub struct FieldId {
@ -328,46 +355,55 @@ pub struct TupleFieldId {
pub struct ConstId(salsa::InternId); pub struct ConstId(salsa::InternId);
type ConstLoc = AssocItemLoc<Const>; type ConstLoc = AssocItemLoc<Const>;
impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const); impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const);
impl_loc!(ConstLoc, id: Const, container: ItemContainerId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StaticId(salsa::InternId); pub struct StaticId(salsa::InternId);
pub type StaticLoc = AssocItemLoc<Static>; pub type StaticLoc = AssocItemLoc<Static>;
impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static); impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
impl_loc!(StaticLoc, id: Static, container: ItemContainerId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TraitId(salsa::InternId); pub struct TraitId(salsa::InternId);
pub type TraitLoc = ItemLoc<Trait>; pub type TraitLoc = ItemLoc<Trait>;
impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait); impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
impl_loc!(TraitLoc, id: Trait, container: ModuleId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TraitAliasId(salsa::InternId); pub struct TraitAliasId(salsa::InternId);
pub type TraitAliasLoc = ItemLoc<TraitAlias>; pub type TraitAliasLoc = ItemLoc<TraitAlias>;
impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias); 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TypeAliasId(salsa::InternId); pub struct TypeAliasId(salsa::InternId);
type TypeAliasLoc = AssocItemLoc<TypeAlias>; type TypeAliasLoc = AssocItemLoc<TypeAlias>;
impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias); 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ImplId(salsa::InternId); pub struct ImplId(salsa::InternId);
type ImplLoc = ItemLoc<Impl>; type ImplLoc = ItemLoc<Impl>;
impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct UseId(salsa::InternId); pub struct UseId(salsa::InternId);
type UseLoc = ItemLoc<Use>; type UseLoc = ItemLoc<Use>;
impl_intern!(UseId, UseLoc, intern_use, lookup_intern_use); 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ExternCrateId(salsa::InternId); pub struct ExternCrateId(salsa::InternId);
type ExternCrateLoc = ItemLoc<ExternCrate>; type ExternCrateLoc = ItemLoc<ExternCrate>;
impl_intern!(ExternCrateId, ExternCrateLoc, intern_extern_crate, lookup_intern_extern_crate); 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ExternBlockId(salsa::InternId); pub struct ExternBlockId(salsa::InternId);
type ExternBlockLoc = ItemLoc<ExternBlock>; type ExternBlockLoc = ItemLoc<ExternBlock>;
impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_extern_block); 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MacroExpander { pub enum MacroExpander {
@ -389,6 +425,7 @@ pub struct Macro2Loc {
pub edition: Edition, pub edition: Edition,
} }
impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2); 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct MacroRulesId(salsa::InternId); pub struct MacroRulesId(salsa::InternId);
@ -401,6 +438,7 @@ pub struct MacroRulesLoc {
pub edition: Edition, pub edition: Edition,
} }
impl_intern!(MacroRulesId, MacroRulesLoc, intern_macro_rules, lookup_intern_macro_rules); impl_intern!(MacroRulesId, MacroRulesLoc, intern_macro_rules, lookup_intern_macro_rules);
impl_loc!(MacroRulesLoc, id: MacroRules, container: ModuleId);
bitflags::bitflags! { bitflags::bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -421,6 +459,7 @@ pub struct ProcMacroLoc {
pub edition: Edition, pub edition: Edition,
} }
impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_macro); 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct BlockId(salsa::InternId); pub struct BlockId(salsa::InternId);
@ -986,44 +1025,92 @@ impl VariantId {
} }
pub trait HasModule { pub trait HasModule {
/// Returns the enclosing module this thing is defined within.
fn module(&self, db: &dyn DefDatabase) -> ModuleId; fn module(&self, db: &dyn DefDatabase) -> ModuleId;
} /// Returns the crate this thing is defined within.
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<N: ItemTreeModItemNode> HasModule for AssocItemLoc<N> {
#[inline] #[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId { #[doc(alias = "crate")]
self.container.module(db) fn krate(&self, db: &dyn DefDatabase) -> CrateId {
self.module(db).krate
} }
} }
impl HasModule for AdtId { // In theory this impl should work out for us, but rustc thinks it collides with all the other
fn module(&self, db: &dyn DefDatabase) -> ModuleId { // manual impls that do not have a ModuleId container...
match self { // impl<N, ItemId, Data> HasModule for ItemId
AdtId::StructId(it) => it.lookup(db).container, // where
AdtId::UnionId(it) => it.lookup(db).container, // N: ItemTreeNode,
AdtId::EnumId(it) => it.lookup(db).container, // ItemId: for<'db> Lookup<Database<'db> = dyn DefDatabase + 'db, Data = Data> + Copy,
} // Data: ItemTreeLoc<Id = N, Container = ModuleId>,
} // {
} // #[inline]
// fn module(&self, db: &dyn DefDatabase) -> ModuleId {
// self.lookup(db).container()
// }
// }
impl HasModule for EnumId { impl<N, ItemId> HasModule for ItemId
where
N: ItemTreeNode,
ItemId: for<'db> Lookup<Database<'db> = dyn DefDatabase + 'db, Data = ItemLoc<N>> + Copy,
{
#[inline] #[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId { fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.lookup(db).container 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<N, ItemId> HasModule for ItemId
// where
// N: ItemTreeModItemNode,
// ItemId: for<'db> Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<N>> + 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<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<impl ItemTreeNode>>,
) -> 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 { impl HasModule for EnumVariantId {
#[inline] #[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId { fn module(&self, db: &dyn DefDatabase) -> ModuleId {
@ -1031,46 +1118,81 @@ impl HasModule for EnumVariantId {
} }
} }
impl HasModule for ExternCrateId { impl HasModule for MacroRulesId {
#[inline] #[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId { fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.lookup(db).container 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 { impl HasModule for VariantId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId { fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match self { match *self {
VariantId::EnumVariantId(it) => it.lookup(db).parent.module(db), VariantId::EnumVariantId(it) => it.module(db),
VariantId::StructId(it) => it.lookup(db).container, VariantId::StructId(it) => it.module(db),
VariantId::UnionId(it) => it.lookup(db).container, VariantId::UnionId(it) => it.module(db),
} }
} }
} }
impl HasModule for MacroId { impl HasModule for MacroId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId { fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match self { match *self {
MacroId::MacroRulesId(it) => it.lookup(db).container, MacroId::MacroRulesId(it) => it.module(db),
MacroId::Macro2Id(it) => it.lookup(db).container, MacroId::Macro2Id(it) => it.module(db),
MacroId::ProcMacroId(it) => it.lookup(db).container.into(), MacroId::ProcMacroId(it) => it.module(db),
} }
} }
} }
impl HasModule for TypeOwnerId { impl HasModule for TypeOwnerId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId { fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match self { match *self {
TypeOwnerId::FunctionId(it) => it.lookup(db).module(db), TypeOwnerId::FunctionId(it) => it.module(db),
TypeOwnerId::StaticId(it) => it.lookup(db).module(db), TypeOwnerId::StaticId(it) => it.module(db),
TypeOwnerId::ConstId(it) => it.lookup(db).module(db), TypeOwnerId::ConstId(it) => it.module(db),
TypeOwnerId::InTypeConstId(it) => it.lookup(db).owner.module(db),
TypeOwnerId::AdtId(it) => it.module(db), TypeOwnerId::AdtId(it) => it.module(db),
TypeOwnerId::TraitId(it) => it.lookup(db).container, TypeOwnerId::TraitId(it) => it.module(db),
TypeOwnerId::TraitAliasId(it) => it.lookup(db).container, TypeOwnerId::TraitAliasId(it) => it.module(db),
TypeOwnerId::TypeAliasId(it) => it.lookup(db).module(db), TypeOwnerId::TypeAliasId(it) => it.module(db),
TypeOwnerId::ImplId(it) => it.lookup(db).container, TypeOwnerId::ImplId(it) => it.module(db),
TypeOwnerId::EnumVariantId(it) => it.lookup(db).parent.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 { impl HasModule for DefWithBodyId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId { fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match self { match self {
DefWithBodyId::FunctionId(it) => it.lookup(db).module(db), DefWithBodyId::FunctionId(it) => it.module(db),
DefWithBodyId::StaticId(it) => it.lookup(db).module(db), DefWithBodyId::StaticId(it) => it.module(db),
DefWithBodyId::ConstId(it) => it.lookup(db).module(db), DefWithBodyId::ConstId(it) => it.module(db),
DefWithBodyId::VariantId(it) => it.lookup(db).parent.module(db), DefWithBodyId::VariantId(it) => it.module(db),
DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db), DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db),
} }
} }
@ -1090,32 +1212,18 @@ impl HasModule for DefWithBodyId {
impl HasModule for GenericDefId { impl HasModule for GenericDefId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId { fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match self { match self {
GenericDefId::FunctionId(it) => it.lookup(db).module(db), GenericDefId::FunctionId(it) => it.module(db),
GenericDefId::AdtId(it) => it.module(db), GenericDefId::AdtId(it) => it.module(db),
GenericDefId::TraitId(it) => it.lookup(db).container, GenericDefId::TraitId(it) => it.module(db),
GenericDefId::TraitAliasId(it) => it.lookup(db).container, GenericDefId::TraitAliasId(it) => it.module(db),
GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), GenericDefId::TypeAliasId(it) => it.module(db),
GenericDefId::ImplId(it) => it.lookup(db).container, GenericDefId::ImplId(it) => it.module(db),
GenericDefId::EnumVariantId(it) => it.lookup(db).parent.lookup(db).container, GenericDefId::EnumVariantId(it) => it.module(db),
GenericDefId::ConstId(it) => it.lookup(db).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 { impl ModuleDefId {
/// Returns the module containing `self` (or `self`, if `self` is itself a module). /// 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<ModuleId> { pub fn module(&self, db: &dyn DefDatabase) -> Option<ModuleId> {
Some(match self { Some(match self {
ModuleDefId::ModuleId(id) => *id, 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::AdtId(id) => id.module(db),
ModuleDefId::EnumVariantId(id) => id.lookup(db).parent.module(db), ModuleDefId::EnumVariantId(id) => id.module(db),
ModuleDefId::ConstId(id) => id.lookup(db).container.module(db), ModuleDefId::ConstId(id) => id.module(db),
ModuleDefId::StaticId(id) => id.lookup(db).module(db), ModuleDefId::StaticId(id) => id.module(db),
ModuleDefId::TraitId(id) => id.lookup(db).container, ModuleDefId::TraitId(id) => id.module(db),
ModuleDefId::TraitAliasId(id) => id.lookup(db).container, ModuleDefId::TraitAliasId(id) => id.module(db),
ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db), ModuleDefId::TypeAliasId(id) => id.module(db),
ModuleDefId::MacroId(id) => id.module(db), ModuleDefId::MacroId(id) => id.module(db),
ModuleDefId::BuiltinType(_) => return None, ModuleDefId::BuiltinType(_) => return None,
}) })
@ -1139,31 +1247,28 @@ impl ModuleDefId {
impl AttrDefId { impl AttrDefId {
pub fn krate(&self, db: &dyn DefDatabase) -> CrateId { pub fn krate(&self, db: &dyn DefDatabase) -> CrateId {
match self { match *self {
AttrDefId::ModuleId(it) => it.krate, AttrDefId::ModuleId(it) => it.krate,
AttrDefId::FieldId(it) => it.parent.module(db).krate, AttrDefId::FieldId(it) => it.parent.krate(db),
AttrDefId::AdtId(it) => it.module(db).krate, AttrDefId::AdtId(it) => it.krate(db),
AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate, AttrDefId::FunctionId(it) => it.krate(db),
AttrDefId::EnumVariantId(it) => it.lookup(db).parent.module(db).krate, AttrDefId::EnumVariantId(it) => it.krate(db),
AttrDefId::StaticId(it) => it.lookup(db).module(db).krate, AttrDefId::StaticId(it) => it.krate(db),
AttrDefId::ConstId(it) => it.lookup(db).module(db).krate, AttrDefId::ConstId(it) => it.krate(db),
AttrDefId::TraitId(it) => it.lookup(db).container.krate, AttrDefId::TraitId(it) => it.krate(db),
AttrDefId::TraitAliasId(it) => it.lookup(db).container.krate, AttrDefId::TraitAliasId(it) => it.krate(db),
AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate, AttrDefId::TypeAliasId(it) => it.krate(db),
AttrDefId::ImplId(it) => it.lookup(db).container.krate, AttrDefId::ImplId(it) => it.krate(db),
AttrDefId::ExternBlockId(it) => it.lookup(db).container.krate, AttrDefId::ExternBlockId(it) => it.krate(db),
AttrDefId::GenericParamId(it) => { AttrDefId::GenericParamId(it) => match it {
match it { GenericParamId::TypeParamId(it) => it.parent(),
GenericParamId::TypeParamId(it) => it.parent(), GenericParamId::ConstParamId(it) => it.parent(),
GenericParamId::ConstParamId(it) => it.parent(), GenericParamId::LifetimeParamId(it) => it.parent,
GenericParamId::LifetimeParamId(it) => it.parent,
}
.module(db)
.krate
} }
AttrDefId::MacroId(it) => it.module(db).krate, .krate(db),
AttrDefId::ExternCrateId(it) => it.lookup(db).container.krate, AttrDefId::MacroId(it) => it.krate(db),
AttrDefId::UseId(it) => it.lookup(db).container.krate, AttrDefId::ExternCrateId(it) => it.krate(db),
AttrDefId::UseId(it) => it.krate(db),
} }
} }
} }

View file

@ -33,8 +33,8 @@ use crate::{
db::DefDatabase, db::DefDatabase,
item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports}, item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
item_tree::{ item_tree::{
self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode,
ItemTreeModItemNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
}, },
macro_call_as_call_id, macro_call_as_call_id_with_eager, macro_call_as_call_id, macro_call_as_call_id_with_eager,
nameres::{ nameres::{

View file

@ -4,91 +4,29 @@ use hir_expand::InFile;
use la_arena::ArenaMap; use la_arena::ArenaMap;
use syntax::ast; use syntax::ast;
use crate::{ use crate::{db::DefDatabase, item_tree::ItemTreeNode, ItemTreeLoc, Lookup, UseId};
db::DefDatabase, item_tree::ItemTreeModItemNode, AssocItemLoc, EnumVariantLoc, ItemLoc, Lookup,
Macro2Loc, MacroRulesLoc, ProcMacroLoc, UseId,
};
pub trait HasSource { pub trait HasSource {
type Value; type Value;
fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Value>; fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Value>;
} }
impl<N: ItemTreeModItemNode> HasSource for AssocItemLoc<N> { impl<T> HasSource for T
type Value = N::Source; where
T: ItemTreeLoc,
fn source(&self, db: &dyn DefDatabase) -> InFile<N::Source> { T::Id: ItemTreeNode,
let tree = self.id.item_tree(db); {
let ast_id_map = db.ast_id_map(self.id.file_id()); type Value = <T::Id as ItemTreeNode>::Source;
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<N: ItemTreeModItemNode> HasSource for ItemLoc<N> {
type Value = N::Source;
fn source(&self, db: &dyn DefDatabase) -> InFile<N::Source> {
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<ast::Variant> {
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;
fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Value> { fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Value> {
let tree = self.id.item_tree(db); let id = self.item_tree_id();
let ast_id_map = db.ast_id_map(self.id.file_id()); let file_id = id.file_id();
let root = db.parse_or_expand(self.id.file_id()); let tree = id.item_tree(db);
let node = &tree[self.id.value]; 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)) InFile::new(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<Self::Value> {
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<Self::Value> {
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))
} }
} }

View file

@ -814,9 +814,8 @@ impl HirDisplay for Ty {
// Don't count Sized but count when it absent // Don't count Sized but count when it absent
// (i.e. when explicit ?Sized bound is set). // (i.e. when explicit ?Sized bound is set).
let default_sized = SizedByDefault::Sized { let default_sized =
anchor: func.lookup(db.upcast()).module(db.upcast()).krate(), SizedByDefault::Sized { anchor: func.krate(db.upcast()) };
};
let sized_bounds = bounds let sized_bounds = bounds
.skip_binders() .skip_binders()
.iter() .iter()
@ -1025,7 +1024,7 @@ impl HirDisplay for Ty {
let data = let data =
(*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
let bounds = data.substitute(Interner, &parameters); let bounds = data.substitute(Interner, &parameters);
let krate = func.lookup(db.upcast()).module(db.upcast()).krate(); let krate = func.krate(db.upcast());
write_bounds_like_dyn_trait_with_prefix( write_bounds_like_dyn_trait_with_prefix(
f, f,
"impl", "impl",
@ -1191,7 +1190,7 @@ impl HirDisplay for Ty {
let data = let data =
(*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
let bounds = data.substitute(Interner, &opaque_ty.substitution); 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( write_bounds_like_dyn_trait_with_prefix(
f, f,
"impl", "impl",

View file

@ -1225,7 +1225,7 @@ impl<'a> TyLoweringContext<'a> {
.collect(); .collect();
if !ctx.unsized_types.borrow().contains(&self_ty) { 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 let sized_trait = ctx
.db .db
.lang_item(krate, LangItem::Sized) .lang_item(krate, LangItem::Sized)
@ -1824,11 +1824,10 @@ impl CallableDefId {
pub fn krate(self, db: &dyn HirDatabase) -> CrateId { pub fn krate(self, db: &dyn HirDatabase) -> CrateId {
let db = db.upcast(); let db = db.upcast();
match self { match self {
CallableDefId::FunctionId(f) => f.lookup(db).module(db), CallableDefId::FunctionId(f) => f.krate(db),
CallableDefId::StructId(s) => s.lookup(db).container, CallableDefId::StructId(s) => s.krate(db),
CallableDefId::EnumVariantId(e) => e.module(db), CallableDefId::EnumVariantId(e) => e.krate(db),
} }
.krate()
} }
} }

View file

@ -44,7 +44,7 @@ use hir_def::{
data::adt::VariantData, data::adt::VariantData,
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat}, hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat},
item_tree::ItemTreeModItemNode, item_tree::ItemTreeNode,
lang_item::LangItemTarget, lang_item::LangItemTarget,
layout::{self, ReprOptions, TargetDataLayout}, layout::{self, ReprOptions, TargetDataLayout},
nameres::{self, diagnostics::DefDiagnostic}, nameres::{self, diagnostics::DefDiagnostic},
@ -1768,7 +1768,7 @@ pub struct Function {
impl Function { impl Function {
pub fn module(self, db: &dyn HirDatabase) -> Module { 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 { pub fn name(self, db: &dyn HirDatabase) -> Name {
@ -1909,8 +1909,7 @@ impl Function {
{ {
return None; return None;
} }
let loc = self.id.lookup(db.upcast()); let def_map = db.crate_def_map(HasModule::krate(&self.id, db.upcast()));
let def_map = db.crate_def_map(loc.krate(db).into());
def_map.fn_as_proc_macro(self.id).map(|id| Macro { id: id.into() }) def_map.fn_as_proc_macro(self.id).map(|id| Macro { id: id.into() })
} }
@ -2119,7 +2118,7 @@ pub struct Const {
impl Const { impl Const {
pub fn module(self, db: &dyn HirDatabase) -> Module { 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<Name> { pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
@ -2174,7 +2173,7 @@ pub struct Static {
impl Static { impl Static {
pub fn module(self, db: &dyn HirDatabase) -> Module { 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 { pub fn name(self, db: &dyn HirDatabase) -> Name {
@ -2293,7 +2292,7 @@ impl TypeAlias {
} }
pub fn module(self, db: &dyn HirDatabase) -> Module { 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<TypeRef> { pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> {
@ -2516,11 +2515,13 @@ pub enum AssocItem {
Const(Const), Const(Const),
TypeAlias(TypeAlias), TypeAlias(TypeAlias),
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum AssocItemContainer { pub enum AssocItemContainer {
Trait(Trait), Trait(Trait),
Impl(Impl), Impl(Impl),
} }
pub trait AsAssocItem { pub trait AsAssocItem {
fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>; fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>;
} }
@ -2530,16 +2531,19 @@ impl AsAssocItem for Function {
as_assoc_item(db, AssocItem::Function, self.id) as_assoc_item(db, AssocItem::Function, self.id)
} }
} }
impl AsAssocItem for Const { impl AsAssocItem for Const {
fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> { fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
as_assoc_item(db, AssocItem::Const, self.id) as_assoc_item(db, AssocItem::Const, self.id)
} }
} }
impl AsAssocItem for TypeAlias { impl AsAssocItem for TypeAlias {
fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> { fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
as_assoc_item(db, AssocItem::TypeAlias, self.id) as_assoc_item(db, AssocItem::TypeAlias, self.id)
} }
} }
impl AsAssocItem for ModuleDef { impl AsAssocItem for ModuleDef {
fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> { fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
match self { match self {
@ -2550,6 +2554,7 @@ impl AsAssocItem for ModuleDef {
} }
} }
} }
impl AsAssocItem for DefWithBody { impl AsAssocItem for DefWithBody {
fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> { fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
match self { 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), db: &(dyn HirDatabase + 'db),
ctor: CTOR, ctor: impl FnOnce(DEF) -> AssocItem,
id: ID, id: ID,
) -> Option<AssocItem> ) -> Option<AssocItem>
where where
ID: Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<AST>>, ID: Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<LOC>>,
DEF: From<ID>, DEF: From<ID>,
CTOR: FnOnce(DEF) -> AssocItem, LOC: ItemTreeNode,
AST: ItemTreeModItemNode,
{ {
match id.lookup(db.upcast()).container { match id.lookup(db.upcast()).container {
ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))), ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
@ -2609,27 +2613,34 @@ impl AssocItem {
} }
} }
pub fn containing_trait(self, db: &dyn HirDatabase) -> Option<Trait> { pub fn container_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
match self.container(db) { match self.container(db) {
AssocItemContainer::Trait(t) => Some(t), AssocItemContainer::Trait(t) => Some(t),
_ => None, _ => None,
} }
} }
pub fn containing_trait_impl(self, db: &dyn HirDatabase) -> Option<Trait> { pub fn implemented_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
match self.container(db) { match self.container(db) {
AssocItemContainer::Impl(i) => i.trait_(db), AssocItemContainer::Impl(i) => i.trait_(db),
_ => None, _ => None,
} }
} }
pub fn containing_trait_or_trait_impl(self, db: &dyn HirDatabase) -> Option<Trait> { pub fn container_or_implemented_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
match self.container(db) { match self.container(db) {
AssocItemContainer::Trait(t) => Some(t), AssocItemContainer::Trait(t) => Some(t),
AssocItemContainer::Impl(i) => i.trait_(db), AssocItemContainer::Impl(i) => i.trait_(db),
} }
} }
pub fn implementing_ty(self, db: &dyn HirDatabase) -> Option<Type> {
match self.container(db) {
AssocItemContainer::Impl(i) => Some(i.self_ty(db)),
_ => None,
}
}
pub fn as_function(self) -> Option<Function> { pub fn as_function(self) -> Option<Function> {
match self { match self {
Self::Function(v) => Some(v), Self::Function(v) => Some(v),
@ -3321,7 +3332,7 @@ impl Impl {
} }
pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> { pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
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 { pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
@ -3677,7 +3688,7 @@ impl Type {
.and_then(|it| { .and_then(|it| {
let into_future_fn = it.as_function()?; let into_future_fn = it.as_function()?;
let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?; 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) Some(into_future_trait.id)
}) })
.or_else(|| { .or_else(|| {

View file

@ -163,9 +163,8 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
return None; return None;
} }
let assoc = func.as_assoc_item(ctx.sema.db)?; let assoc = func.as_assoc_item(ctx.sema.db)?;
match assoc.container(ctx.sema.db) { if !assoc.implementing_ty(ctx.sema.db)?.is_bool() {
hir::AssocItemContainer::Impl(impl_) if impl_.self_ty(ctx.sema.db).is_bool() => {} return None;
_ => return None,
} }
let target = mcall.syntax().text_range(); let target = mcall.syntax().text_range();

View file

@ -364,7 +364,7 @@ fn is_in_trait_impl(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> bool {
ctx.sema ctx.sema
.to_def(ast_func) .to_def(ast_func)
.and_then(|hir_func| hir_func.as_assoc_item(ctx.db())) .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() .is_some()
} }
@ -373,7 +373,7 @@ fn is_in_trait_def(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> bool {
ctx.sema ctx.sema
.to_def(ast_func) .to_def(ast_func)
.and_then(|hir_func| hir_func.as_assoc_item(ctx.db())) .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() .is_some()
} }

View file

@ -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 fnc = sema.resolve_method_call(&method_call)?;
let scope = sema.scope(method_call.syntax())?; let scope = sema.scope(method_call.syntax())?;
// Check if the method call refers to Into trait. // 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()? == FamousDefs(sema, scope.krate()).core_convert_Into()?
{ {
let type_call = sema.type_of_expr(&method_call.clone().into())?; let type_call = sema.type_of_expr(&method_call.clone().into())?;

View file

@ -203,7 +203,7 @@ fn item_as_trait(db: &RootDatabase, item: hir::ItemInNs) -> Option<hir::Trait> {
match item_module_def { match item_module_def {
hir::ModuleDef::Trait(trait_) => Some(trait_), 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),
} }
} }

View file

@ -112,7 +112,7 @@ impl<'a> RenderContext<'a> {
}; };
is_assoc_deprecated is_assoc_deprecated
|| assoc || assoc
.containing_trait_or_trait_impl(db) .container_or_implemented_trait(db)
.map(|trait_| self.is_deprecated(trait_)) .map(|trait_| self.is_deprecated(trait_))
.unwrap_or(false) .unwrap_or(false)
} }

View file

@ -23,7 +23,7 @@ fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem>
.set_relevance(ctx.completion_relevance()); .set_relevance(ctx.completion_relevance());
if let Some(actm) = const_.as_assoc_item(db) { 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()); item.trait_name(trt.name(db).to_smol_str());
} }
} }

View file

@ -75,7 +75,7 @@ fn render(
let ret_type = func.ret_type(db); let ret_type = func.ret_type(db);
let assoc_item = func.as_assoc_item(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_op_method = trait_.map_or(false, |trait_| completion.is_ops_trait(trait_));
let is_item_from_notable_trait = let is_item_from_notable_trait =
@ -145,7 +145,7 @@ fn render(
} }
None => { None => {
if let Some(actm) = assoc_item { 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()); item.trait_name(trt.name(db).to_smol_str());
} }
} }

View file

@ -47,7 +47,7 @@ fn render(
.set_relevance(ctx.completion_relevance()); .set_relevance(ctx.completion_relevance());
if let Some(actm) = type_alias.as_assoc_item(db) { 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()); item.trait_name(trt.name(db).to_smol_str());
} }
} }

View file

@ -206,7 +206,7 @@ impl Definition {
// docs are missing, for assoc items of trait impls try to fall back to the docs of the // docs are missing, for assoc items of trait impls try to fall back to the docs of the
// original item of the trait // original item of the trait
let assoc = self.as_assoc_item(db)?; 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 name = Some(assoc.name(db)?);
let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?; let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?;
item.docs(db) item.docs(db)

View file

@ -529,7 +529,7 @@ fn trait_applicable_items(
return None; 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) { if related_traits.contains(&assoc_item_trait) {
return None; return None;
} }
@ -550,8 +550,7 @@ fn trait_applicable_items(
None, None,
|assoc| { |assoc| {
if required_assoc_items.contains(&assoc) { if required_assoc_items.contains(&assoc) {
let located_trait = let located_trait = assoc.container_trait(db).filter(|&it| scope_filter(it))?;
assoc.containing_trait(db).filter(|&it| scope_filter(it))?;
let trait_item = ItemInNs::from(ModuleDef::from(located_trait)); let trait_item = ItemInNs::from(ModuleDef::from(located_trait));
let import_path = trait_import_paths let import_path = trait_import_paths
.entry(trait_item) .entry(trait_item)
@ -576,8 +575,7 @@ fn trait_applicable_items(
|function| { |function| {
let assoc = function.as_assoc_item(db)?; let assoc = function.as_assoc_item(db)?;
if required_assoc_items.contains(&assoc) { if required_assoc_items.contains(&assoc) {
let located_trait = let located_trait = assoc.container_trait(db).filter(|&it| scope_filter(it))?;
assoc.containing_trait(db).filter(|&it| scope_filter(it))?;
let trait_item = ItemInNs::from(ModuleDef::from(located_trait)); let trait_item = ItemInNs::from(ModuleDef::from(located_trait));
let import_path = trait_import_paths let import_path = trait_import_paths
.entry(trait_item) .entry(trait_item)

View file

@ -75,7 +75,7 @@ pub fn get_missing_assoc_items(
pub(crate) fn convert_to_def_in_trait(db: &dyn HirDatabase, def: Definition) -> Definition { pub(crate) fn convert_to_def_in_trait(db: &dyn HirDatabase, def: Definition) -> Definition {
(|| { (|| {
let assoc = def.as_assoc_item(db)?; 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_) assoc_item_of_trait(db, assoc, trait_)
})() })()
.unwrap_or(def) .unwrap_or(def)

View file

@ -668,7 +668,7 @@ fn get_assoc_item_fragment(db: &dyn HirDatabase, assoc_item: hir::AssocItem) ->
Some(match assoc_item { Some(match assoc_item {
AssocItem::Function(function) => { AssocItem::Function(function) => {
let is_trait_method = 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. // This distinction may get more complicated when specialization is available.
// Rustdoc makes this decision based on whether a method 'has defaultness'. // Rustdoc makes this decision based on whether a method 'has defaultness'.
// Currently this is only the case for provided trait methods. // Currently this is only the case for provided trait methods.

View file

@ -61,7 +61,7 @@ pub(crate) fn goto_declaration(
_ => None, _ => None,
}?; }?;
let trait_ = assoc.containing_trait_impl(db)?; let trait_ = assoc.implemented_trait(db)?;
let name = Some(assoc.name(db)?); let name = Some(assoc.name(db)?);
let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?; let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?;
item.try_to_nav(db) item.try_to_nav(db)

View file

@ -182,11 +182,7 @@ fn try_filter_trait_item_definition(
match assoc { match assoc {
AssocItem::Function(..) => None, AssocItem::Function(..) => None,
AssocItem::Const(..) | AssocItem::TypeAlias(..) => { AssocItem::Const(..) | AssocItem::TypeAlias(..) => {
let imp = match assoc.container(db) { let trait_ = assoc.implemented_trait(db)?;
hir::AssocItemContainer::Impl(imp) => imp,
_ => return None,
};
let trait_ = imp.trait_(db)?;
let name = def.name(db)?; let name = def.name(db)?;
let discri_value = discriminant(&assoc); let discri_value = discriminant(&assoc);
trait_ trait_

View file

@ -60,13 +60,13 @@ pub(crate) fn goto_implementation(
Definition::Function(f) => { Definition::Function(f) => {
let assoc = f.as_assoc_item(sema.db)?; let assoc = f.as_assoc_item(sema.db)?;
let name = assoc.name(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) impls_for_trait_item(&sema, trait_, name)
} }
Definition::Const(c) => { Definition::Const(c) => {
let assoc = c.as_assoc_item(sema.db)?; let assoc = c.as_assoc_item(sema.db)?;
let name = assoc.name(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) impls_for_trait_item(&sema, trait_, name)
} }
_ => return None, _ => return None,

View file

@ -442,8 +442,7 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
.for_each(|name| format_to!(path, "{}::", name.display(db))); .for_each(|name| format_to!(path, "{}::", name.display(db)));
// This probably belongs to canonical_path? // This probably belongs to canonical_path?
if let Some(assoc_item) = def.as_assoc_item(db) { if let Some(assoc_item) = def.as_assoc_item(db) {
if let hir::AssocItemContainer::Impl(imp) = assoc_item.container(db) { if let Some(ty) = assoc_item.implementing_ty(db) {
let ty = imp.self_ty(db);
if let Some(adt) = ty.as_adt() { if let Some(adt) = ty.as_adt() {
let name = adt.name(db); let name = adt.name(db);
let mut ty_args = ty.generic_parameters(db).peekable(); let mut ty_args = ty.generic_parameters(db).peekable();

View file

@ -559,7 +559,7 @@ fn highlight_method_call(
} }
if func if func
.as_assoc_item(sema.db) .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() .is_some()
{ {
h |= HlMod::Trait; h |= HlMod::Trait;