From 66311e12626f19d8b11473e0faebfa3c940200c8 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 19 Jul 2021 14:53:18 +0200 Subject: [PATCH] Add `TreeId` to identify `ItemTree`s With per-block `ItemTree`s, the file ID is not enough to identify an `ItemTree`. --- crates/hir_def/src/data.rs | 25 ++++----- crates/hir_def/src/item_tree.rs | 43 ++++++++++++--- crates/hir_def/src/nameres/collector.rs | 70 ++++++++++++++----------- 3 files changed, 87 insertions(+), 51 deletions(-) diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 52cb7777bbe..985aa568f22 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs @@ -10,7 +10,7 @@ use crate::{ body::Expander, db::DefDatabase, intern::Interned, - item_tree::{AssocItem, FnFlags, ItemTreeId, ModItem, Param}, + item_tree::{self, AssocItem, FnFlags, ItemTreeId, ModItem, Param}, type_ref::{TraitRef, TypeBound, TypeRef}, visibility::RawVisibility, AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, @@ -171,7 +171,7 @@ impl TraitData { module_id, &mut expander, tr_def.items.iter().copied(), - tr_loc.id.file_id(), + tr_loc.id.tree_id(), container, 100, ); @@ -228,7 +228,7 @@ impl ImplData { module_id, &mut expander, impl_def.items.iter().copied(), - impl_loc.id.file_id(), + impl_loc.id.tree_id(), container, 100, ); @@ -290,7 +290,7 @@ fn collect_items( module: ModuleId, expander: &mut Expander, assoc_items: impl Iterator, - file_id: crate::HirFileId, + tree_id: item_tree::TreeId, container: AssocContainerId, limit: usize, ) -> Vec<(Name, AssocItemId)> { @@ -298,7 +298,7 @@ fn collect_items( return Vec::new(); } - let item_tree = db.file_item_tree(file_id); + let item_tree = tree_id.item_tree(db); let crate_graph = db.crate_graph(); let cfg_options = &crate_graph[module.krate].cfg_options; @@ -312,7 +312,7 @@ fn collect_items( match item { AssocItem::Function(id) => { let item = &item_tree[id]; - let def = FunctionLoc { container, id: ItemTreeId::new(file_id, id) }.intern(db); + let def = FunctionLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(db); items.push((item.name.clone(), def.into())); } AssocItem::Const(id) => { @@ -321,25 +321,26 @@ fn collect_items( Some(name) => name, None => continue, }; - let def = ConstLoc { container, id: ItemTreeId::new(file_id, id) }.intern(db); + let def = ConstLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(db); items.push((name, def.into())); } AssocItem::TypeAlias(id) => { let item = &item_tree[id]; - let def = TypeAliasLoc { container, id: ItemTreeId::new(file_id, id) }.intern(db); + let def = TypeAliasLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(db); items.push((item.name.clone(), def.into())); } AssocItem::MacroCall(call) => { let call = &item_tree[call]; - let ast_id_map = db.ast_id_map(file_id); - let root = db.parse_or_expand(file_id).unwrap(); + let ast_id_map = db.ast_id_map(tree_id.file_id()); + let root = db.parse_or_expand(tree_id.file_id()).unwrap(); let call = ast_id_map.get(call.ast_id).to_node(&root); let res = expander.enter_expand(db, call); if let Ok(res) = res { if let Some((mark, mac)) = res.value { let src: InFile = expander.to_source(mac); - let item_tree = db.file_item_tree(src.file_id); + let tree_id = item_tree::TreeId::new(src.file_id, None); + let item_tree = tree_id.item_tree(db); let iter = item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item); items.extend(collect_items( @@ -347,7 +348,7 @@ fn collect_items( module, expander, iter, - src.file_id, + tree_id, container, limit - 1, )); diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 90129a790a1..aa462f2b976 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -67,6 +67,7 @@ use crate::{ path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, visibility::RawVisibility, + BlockId, }; #[derive(Copy, Clone, Eq, PartialEq)] @@ -374,23 +375,51 @@ impl fmt::Debug for FileItemTreeId { } } +/// Identifies a particular [`ItemTree`]. +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +pub struct TreeId { + file: HirFileId, + block: Option, +} + +impl TreeId { + pub(crate) fn new(file: HirFileId, block: Option) -> Self { + Self { file, block } + } + + pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc { + match self.block { + Some(_) => unreachable!("per-block ItemTrees are not yet implemented"), + None => db.file_item_tree(self.file), + } + } + + pub(crate) fn file_id(self) -> HirFileId { + self.file + } +} + #[derive(Debug)] pub struct ItemTreeId { - file: HirFileId, + tree: TreeId, pub value: FileItemTreeId, } impl ItemTreeId { - pub fn new(file: HirFileId, idx: FileItemTreeId) -> Self { - Self { file, value: idx } + pub fn new(tree: TreeId, idx: FileItemTreeId) -> Self { + Self { tree, value: idx } } pub fn file_id(self) -> HirFileId { - self.file + self.tree.file + } + + pub fn tree_id(self) -> TreeId { + self.tree } pub fn item_tree(self, db: &dyn DefDatabase) -> Arc { - db.file_item_tree(self.file) + self.tree.item_tree(db) } } @@ -403,7 +432,7 @@ impl Clone for ItemTreeId { impl PartialEq for ItemTreeId { fn eq(&self, other: &Self) -> bool { - self.file == other.file && self.value == other.value + self.tree == other.tree && self.value == other.value } } @@ -411,7 +440,7 @@ impl Eq for ItemTreeId {} impl Hash for ItemTreeId { fn hash(&self, state: &mut H) { - self.file.hash(state); + self.tree.hash(state); self.value.hash(state); } } diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 79452bba548..74362bb1a4c 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs @@ -31,7 +31,7 @@ use crate::{ item_scope::{ImportType, PerNsGlobImports}, item_tree::{ self, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, MacroCall, MacroDef, - MacroRules, Mod, ModItem, ModKind, + MacroRules, Mod, ModItem, ModKind, TreeId, }, macro_call_as_call_id, nameres::{ @@ -311,7 +311,7 @@ impl DefCollector<'_> { def_collector: &mut *self, macro_depth: 0, module_id, - file_id: file_id.into(), + tree_id: TreeId::new(file_id.into(), None), item_tree: &item_tree, mod_dir: ModDir::root(), } @@ -331,7 +331,8 @@ impl DefCollector<'_> { def_collector: &mut *self, macro_depth: 0, module_id, - file_id: block.file_id, + // FIXME: populate block once we have per-block ItemTrees + tree_id: TreeId::new(block.file_id, None), item_tree: &item_tree, mod_dir: ModDir::root(), } @@ -427,7 +428,7 @@ impl DefCollector<'_> { def_collector: &mut *self, macro_depth: directive.depth, module_id: directive.module_id, - file_id, + tree_id: TreeId::new(file_id, None), item_tree: &item_tree, mod_dir, } @@ -1066,7 +1067,7 @@ impl DefCollector<'_> { def_collector: &mut *self, macro_depth: directive.depth, module_id: directive.module_id, - file_id, + tree_id: TreeId::new(file_id, None), item_tree: &item_tree, mod_dir, } @@ -1113,7 +1114,7 @@ impl DefCollector<'_> { def_collector: &mut *self, macro_depth: directive.depth, module_id: directive.module_id, - file_id, + tree_id: TreeId::new(file_id, None), item_tree: &item_tree, mod_dir, } @@ -1200,7 +1201,7 @@ impl DefCollector<'_> { ModCollector { def_collector: &mut *self, macro_depth: depth, - file_id, + tree_id: TreeId::new(file_id, None), module_id, item_tree: &item_tree, mod_dir, @@ -1295,7 +1296,7 @@ struct ModCollector<'a, 'b> { def_collector: &'a mut DefCollector<'b>, macro_depth: usize, module_id: LocalModuleId, - file_id: HirFileId, + tree_id: TreeId, item_tree: &'a ItemTree, mod_dir: ModDir, } @@ -1362,7 +1363,7 @@ impl ModCollector<'_, '_> { self.def_collector.db, krate, self.item_tree, - ItemTreeId::new(self.file_id, import_id), + ItemTreeId::new(self.tree_id, import_id), ); self.def_collector.unresolved_imports.extend(imports.into_iter().map( |import| ImportDirective { @@ -1379,7 +1380,7 @@ impl ModCollector<'_, '_> { self.def_collector.db, krate, self.item_tree, - ItemTreeId::new(self.file_id, import_id), + ItemTreeId::new(self.tree_id, import_id), ), status: PartialResolvedImport::Unresolved, }) @@ -1391,20 +1392,20 @@ impl ModCollector<'_, '_> { ModItem::Impl(imp) => { let module = self.def_collector.def_map.module_id(self.module_id); let impl_id = - ImplLoc { container: module, id: ItemTreeId::new(self.file_id, imp) } + ImplLoc { container: module, id: ItemTreeId::new(self.tree_id, imp) } .intern(self.def_collector.db); self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id) } ModItem::Function(id) => { let func = &self.item_tree[id]; - let ast_id = InFile::new(self.file_id, func.ast_id); + let ast_id = InFile::new(self.file_id(), func.ast_id); self.collect_proc_macro_def(&func.name, ast_id, &attrs); def = Some(DefData { id: FunctionLoc { container: module.into(), - id: ItemTreeId::new(self.file_id, id), + id: ItemTreeId::new(self.tree_id, id), } .intern(self.def_collector.db) .into(), @@ -1417,7 +1418,7 @@ impl ModCollector<'_, '_> { let it = &self.item_tree[id]; def = Some(DefData { - id: StructLoc { container: module, id: ItemTreeId::new(self.file_id, id) } + id: StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } .intern(self.def_collector.db) .into(), name: &it.name, @@ -1429,7 +1430,7 @@ impl ModCollector<'_, '_> { let it = &self.item_tree[id]; def = Some(DefData { - id: UnionLoc { container: module, id: ItemTreeId::new(self.file_id, id) } + id: UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } .intern(self.def_collector.db) .into(), name: &it.name, @@ -1441,7 +1442,7 @@ impl ModCollector<'_, '_> { let it = &self.item_tree[id]; def = Some(DefData { - id: EnumLoc { container: module, id: ItemTreeId::new(self.file_id, id) } + id: EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } .intern(self.def_collector.db) .into(), name: &it.name, @@ -1453,7 +1454,7 @@ impl ModCollector<'_, '_> { let it = &self.item_tree[id]; let const_id = ConstLoc { container: module.into(), - id: ItemTreeId::new(self.file_id, id), + id: ItemTreeId::new(self.tree_id, id), } .intern(self.def_collector.db); @@ -1478,7 +1479,7 @@ impl ModCollector<'_, '_> { let it = &self.item_tree[id]; def = Some(DefData { - id: StaticLoc { container: module, id: ItemTreeId::new(self.file_id, id) } + id: StaticLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } .intern(self.def_collector.db) .into(), name: &it.name, @@ -1490,7 +1491,7 @@ impl ModCollector<'_, '_> { let it = &self.item_tree[id]; def = Some(DefData { - id: TraitLoc { container: module, id: ItemTreeId::new(self.file_id, id) } + id: TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } .intern(self.def_collector.db) .into(), name: &it.name, @@ -1504,7 +1505,7 @@ impl ModCollector<'_, '_> { def = Some(DefData { id: TypeAliasLoc { container: module.into(), - id: ItemTreeId::new(self.file_id, id), + id: ItemTreeId::new(self.tree_id, id), } .intern(self.def_collector.db) .into(), @@ -1540,7 +1541,7 @@ impl ModCollector<'_, '_> { ModKind::Inline { items } => { let module_id = self.push_child_module( module.name.clone(), - AstId::new(self.file_id, module.ast_id), + AstId::new(self.file_id(), module.ast_id), None, &self.item_tree[module.visibility], ); @@ -1551,7 +1552,7 @@ impl ModCollector<'_, '_> { def_collector: &mut *self.def_collector, macro_depth: self.macro_depth, module_id, - file_id: self.file_id, + tree_id: self.tree_id, item_tree: self.item_tree, mod_dir, } @@ -1563,9 +1564,10 @@ impl ModCollector<'_, '_> { } // out of line module, resolve, parse and recurse ModKind::Outline {} => { - let ast_id = AstId::new(self.file_id, module.ast_id); + let ast_id = AstId::new(self.tree_id.file_id(), module.ast_id); let db = self.def_collector.db; - match self.mod_dir.resolve_declaration(db, self.file_id, &module.name, path_attr) { + match self.mod_dir.resolve_declaration(db, self.file_id(), &module.name, path_attr) + { Ok((file_id, is_mod_rs, mod_dir)) => { let item_tree = db.file_item_tree(file_id.into()); if item_tree @@ -1585,7 +1587,7 @@ impl ModCollector<'_, '_> { def_collector: &mut *self.def_collector, macro_depth: self.macro_depth, module_id, - file_id: file_id.into(), + tree_id: TreeId::new(file_id.into(), None), item_tree: &item_tree, mod_dir, } @@ -1656,7 +1658,7 @@ impl ModCollector<'_, '_> { /// assumed to be resolved already. fn resolve_attributes(&mut self, attrs: &Attrs, mod_item: ModItem) -> Result<(), ()> { let mut ignore_up_to = - self.def_collector.skip_attrs.get(&InFile::new(self.file_id, mod_item)).copied(); + self.def_collector.skip_attrs.get(&InFile::new(self.file_id(), mod_item)).copied(); let iter = attrs .iter() .dedup_by(|a, b| { @@ -1686,7 +1688,7 @@ impl ModCollector<'_, '_> { log::debug!("non-builtin attribute {}", attr.path); let ast_id = AstIdWithPath::new( - self.file_id, + self.file_id(), mod_item.ast_id(self.item_tree), attr.path.as_ref().clone(), ); @@ -1749,7 +1751,7 @@ impl ModCollector<'_, '_> { match attr.parse_derive() { Some(derive_macros) => { for path in derive_macros { - let ast_id = AstIdWithPath::new(self.file_id, ast_id, path); + let ast_id = AstIdWithPath::new(self.file_id(), ast_id, path); self.def_collector.unresolved_macros.push(MacroDirective { module_id: self.module_id, depth: self.macro_depth + 1, @@ -1776,7 +1778,7 @@ impl ModCollector<'_, '_> { let krate = self.def_collector.def_map.krate; let mac = &self.item_tree[id]; let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); - let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); + let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast()); let export_attr = attrs.by_key("macro_export"); @@ -1841,7 +1843,7 @@ impl ModCollector<'_, '_> { fn collect_macro_def(&mut self, id: FileItemTreeId) { let krate = self.def_collector.def_map.krate; let mac = &self.item_tree[id]; - let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); + let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast()); // Case 1: bulitin macros let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); @@ -1885,7 +1887,7 @@ impl ModCollector<'_, '_> { } fn collect_macro_call(&mut self, mac: &MacroCall) { - let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, (*mac.path).clone()); + let mut ast_id = AstIdWithPath::new(self.file_id(), mac.ast_id, (*mac.path).clone()); // Case 1: try to resolve in legacy scope and expand macro_rules let mut error = None; @@ -1962,7 +1964,7 @@ impl ModCollector<'_, '_> { fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) { let ast_id = item.ast_id(self.item_tree); - let ast_id = InFile::new(self.file_id, ast_id); + let ast_id = InFile::new(self.file_id(), ast_id); self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code( self.module_id, ast_id, @@ -1970,6 +1972,10 @@ impl ModCollector<'_, '_> { self.def_collector.cfg_options.clone(), )); } + + fn file_id(&self) -> HirFileId { + self.tree_id.file_id() + } } #[cfg(test)]