Do impl collection per module, not per crate

This commit is contained in:
Florian Diebold 2019-01-04 19:29:53 +01:00
parent 334ca0d9a7
commit 443ddb73c3
3 changed files with 32 additions and 33 deletions

View File

@ -4,7 +4,7 @@
use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, Cancelable};
use crate::{
Crate, DefLoc, DefId, MacroCallLoc, MacroCallId, Name, HirFileId,
DefLoc, DefId, MacroCallLoc, MacroCallId, Name, HirFileId,
SourceFileItems, SourceItemId,
query_definitions,
FnScopes,
@ -13,7 +13,7 @@
nameres::{ItemMap, InputModuleItems}},
ty::{InferenceResult, Ty},
adt::{StructData, EnumData},
impl_block::CrateImplBlocks,
impl_block::ModuleImplBlocks,
};
salsa::query_group! {
@ -89,9 +89,9 @@ fn module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> {
use fn crate::module::imp::module_tree;
}
fn impls_in_crate(krate: Crate) -> Cancelable<Arc<CrateImplBlocks>> {
fn impls_in_module(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<ModuleImplBlocks>> {
type ImplsInCrateQuery;
use fn crate::impl_block::impls_in_crate;
use fn crate::impl_block::impls_in_module;
}
}

View File

@ -185,8 +185,9 @@ pub fn krate(&self, db: &impl HirDatabase) -> Cancelable<Option<Crate>> {
/// Returns the containing impl block, if this is an impl item.
pub fn impl_block(self, db: &impl HirDatabase) -> Cancelable<Option<ImplBlock>> {
let crate_impls = db.impls_in_crate(ctry!(self.krate(db)?))?;
Ok(ImplBlock::containing(crate_impls, self))
let loc = self.loc(db);
let module_impls = db.impls_in_module(loc.source_root_id, loc.module_id)?;
Ok(ImplBlock::containing(module_impls, self))
}
}

View File

@ -3,36 +3,36 @@
use ra_arena::{Arena, RawId, impl_arena_id};
use ra_syntax::ast::{self, AstNode};
use ra_db::{LocationIntener, Cancelable};
use ra_db::{LocationIntener, Cancelable, SourceRootId};
use crate::{
Crate, DefId, DefLoc, DefKind, SourceItemId, SourceFileItems,
DefId, DefLoc, DefKind, SourceItemId, SourceFileItems,
Module, Function,
db::HirDatabase,
type_ref::TypeRef,
module::{ModuleSourceNode},
module::{ModuleSourceNode, ModuleId},
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImplBlock {
crate_impl_blocks: Arc<CrateImplBlocks>,
module_impl_blocks: Arc<ModuleImplBlocks>,
impl_id: ImplId,
}
impl ImplBlock {
pub(crate) fn containing(
crate_impl_blocks: Arc<CrateImplBlocks>,
module_impl_blocks: Arc<ModuleImplBlocks>,
def_id: DefId,
) -> Option<ImplBlock> {
let impl_id = *crate_impl_blocks.impls_by_def.get(&def_id)?;
let impl_id = *module_impl_blocks.impls_by_def.get(&def_id)?;
Some(ImplBlock {
crate_impl_blocks,
module_impl_blocks,
impl_id,
})
}
fn impl_data(&self) -> &ImplData {
&self.crate_impl_blocks.impls[self.impl_id]
&self.module_impl_blocks.impls[self.impl_id]
}
pub fn target_trait(&self) -> Option<&TypeRef> {
@ -126,17 +126,22 @@ pub fn def_id(&self) -> DefId {
pub struct ImplId(pub RawId);
impl_arena_id!(ImplId);
/// We have to collect all impl blocks in a crate, to later be able to find
/// impls for specific types.
/// Collection of impl blocks is a two-step process: First we collect the blocks
/// per-module; then we build an index of all impl blocks in the crate. This
/// way, we avoid having to do this process for the whole crate whenever someone
/// types in any file; as long as the impl blocks in the file don't change, we
/// don't need to do the second step again.
///
/// (The second step does not yet exist currently.)
#[derive(Debug, PartialEq, Eq)]
pub struct CrateImplBlocks {
pub struct ModuleImplBlocks {
impls: Arena<ImplId, ImplData>,
impls_by_def: FxHashMap<DefId, ImplId>,
}
impl CrateImplBlocks {
impl ModuleImplBlocks {
fn new() -> Self {
CrateImplBlocks {
ModuleImplBlocks {
impls: Arena::default(),
impls_by_def: FxHashMap::default(),
}
@ -159,24 +164,17 @@ fn collect(&mut self, db: &impl HirDatabase, module: Module) -> Cancelable<()> {
}
}
for (_, child) in module.children() {
self.collect(db, child)?;
}
Ok(())
}
}
pub(crate) fn impls_in_crate(
pub(crate) fn impls_in_module(
db: &impl HirDatabase,
krate: Crate,
) -> Cancelable<Arc<CrateImplBlocks>> {
let mut result = CrateImplBlocks::new();
let root_module = if let Some(root) = krate.root_module(db)? {
root
} else {
return Ok(Arc::new(result));
};
result.collect(db, root_module)?;
source_root_id: SourceRootId,
module_id: ModuleId,
) -> Cancelable<Arc<ModuleImplBlocks>> {
let mut result = ModuleImplBlocks::new();
let module = Module::new(db, source_root_id, module_id)?;
result.collect(db, module)?;
Ok(Arc::new(result))
}