Add TreeId to identify ItemTrees

With per-block `ItemTree`s, the file ID is not enough to identify an
`ItemTree`.
This commit is contained in:
Jonas Schievink 2021-07-19 14:53:18 +02:00
parent 64bf67c5aa
commit 66311e1262
3 changed files with 87 additions and 51 deletions

View File

@ -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<Item = AssocItem>,
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<ast::MacroItems> = 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,
));

View File

@ -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<N: ItemTreeNode> fmt::Debug for FileItemTreeId<N> {
}
}
/// Identifies a particular [`ItemTree`].
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub struct TreeId {
file: HirFileId,
block: Option<BlockId>,
}
impl TreeId {
pub(crate) fn new(file: HirFileId, block: Option<BlockId>) -> Self {
Self { file, block }
}
pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> {
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<N: ItemTreeNode> {
file: HirFileId,
tree: TreeId,
pub value: FileItemTreeId<N>,
}
impl<N: ItemTreeNode> ItemTreeId<N> {
pub fn new(file: HirFileId, idx: FileItemTreeId<N>) -> Self {
Self { file, value: idx }
pub fn new(tree: TreeId, idx: FileItemTreeId<N>) -> 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<ItemTree> {
db.file_item_tree(self.file)
self.tree.item_tree(db)
}
}
@ -403,7 +432,7 @@ impl<N: ItemTreeNode> Clone for ItemTreeId<N> {
impl<N: ItemTreeNode> PartialEq for ItemTreeId<N> {
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<N: ItemTreeNode> Eq for ItemTreeId<N> {}
impl<N: ItemTreeNode> Hash for ItemTreeId<N> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.file.hash(state);
self.tree.hash(state);
self.value.hash(state);
}
}

View File

@ -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<MacroDef>) {
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)]