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_syntax::{SyntaxNode, SourceFileNode};
use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, Cancelable}; use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, Cancelable};
use crate::{ use crate::{
Crate, DefLoc, DefId, MacroCallLoc, MacroCallId, Name, HirFileId, DefLoc, DefId, MacroCallLoc, MacroCallId, Name, HirFileId,
SourceFileItems, SourceItemId, SourceFileItems, SourceItemId,
query_definitions, query_definitions,
FnScopes, FnScopes,
@ -13,7 +13,7 @@ use crate::{
nameres::{ItemMap, InputModuleItems}}, nameres::{ItemMap, InputModuleItems}},
ty::{InferenceResult, Ty}, ty::{InferenceResult, Ty},
adt::{StructData, EnumData}, adt::{StructData, EnumData},
impl_block::CrateImplBlocks, impl_block::ModuleImplBlocks,
}; };
salsa::query_group! { salsa::query_group! {
@ -89,9 +89,9 @@ pub trait HirDatabase: SyntaxDatabase
use fn crate::module::imp::module_tree; 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; type ImplsInCrateQuery;
use fn crate::impl_block::impls_in_crate; use fn crate::impl_block::impls_in_module;
} }
} }

View File

@ -185,8 +185,9 @@ impl DefId {
/// Returns the containing impl block, if this is an impl item. /// Returns the containing impl block, if this is an impl item.
pub fn impl_block(self, db: &impl HirDatabase) -> Cancelable<Option<ImplBlock>> { pub fn impl_block(self, db: &impl HirDatabase) -> Cancelable<Option<ImplBlock>> {
let crate_impls = db.impls_in_crate(ctry!(self.krate(db)?))?; let loc = self.loc(db);
Ok(ImplBlock::containing(crate_impls, self)) 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 rustc_hash::FxHashMap;
use ra_arena::{Arena, RawId, impl_arena_id}; use ra_arena::{Arena, RawId, impl_arena_id};
use ra_syntax::ast::{self, AstNode}; use ra_syntax::ast::{self, AstNode};
use ra_db::{LocationIntener, Cancelable}; use ra_db::{LocationIntener, Cancelable, SourceRootId};
use crate::{ use crate::{
Crate, DefId, DefLoc, DefKind, SourceItemId, SourceFileItems, DefId, DefLoc, DefKind, SourceItemId, SourceFileItems,
Module, Function, Module, Function,
db::HirDatabase, db::HirDatabase,
type_ref::TypeRef, type_ref::TypeRef,
module::{ModuleSourceNode}, module::{ModuleSourceNode, ModuleId},
}; };
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImplBlock { pub struct ImplBlock {
crate_impl_blocks: Arc<CrateImplBlocks>, module_impl_blocks: Arc<ModuleImplBlocks>,
impl_id: ImplId, impl_id: ImplId,
} }
impl ImplBlock { impl ImplBlock {
pub(crate) fn containing( pub(crate) fn containing(
crate_impl_blocks: Arc<CrateImplBlocks>, module_impl_blocks: Arc<ModuleImplBlocks>,
def_id: DefId, def_id: DefId,
) -> Option<ImplBlock> { ) -> 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 { Some(ImplBlock {
crate_impl_blocks, module_impl_blocks,
impl_id, impl_id,
}) })
} }
fn impl_data(&self) -> &ImplData { 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> { pub fn target_trait(&self) -> Option<&TypeRef> {
@ -126,17 +126,22 @@ impl ImplItem {
pub struct ImplId(pub RawId); pub struct ImplId(pub RawId);
impl_arena_id!(ImplId); impl_arena_id!(ImplId);
/// We have to collect all impl blocks in a crate, to later be able to find /// Collection of impl blocks is a two-step process: First we collect the blocks
/// impls for specific types. /// 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)] #[derive(Debug, PartialEq, Eq)]
pub struct CrateImplBlocks { pub struct ModuleImplBlocks {
impls: Arena<ImplId, ImplData>, impls: Arena<ImplId, ImplData>,
impls_by_def: FxHashMap<DefId, ImplId>, impls_by_def: FxHashMap<DefId, ImplId>,
} }
impl CrateImplBlocks { impl ModuleImplBlocks {
fn new() -> Self { fn new() -> Self {
CrateImplBlocks { ModuleImplBlocks {
impls: Arena::default(), impls: Arena::default(),
impls_by_def: FxHashMap::default(), impls_by_def: FxHashMap::default(),
} }
@ -159,24 +164,17 @@ impl CrateImplBlocks {
} }
} }
for (_, child) in module.children() {
self.collect(db, child)?;
}
Ok(()) Ok(())
} }
} }
pub(crate) fn impls_in_crate( pub(crate) fn impls_in_module(
db: &impl HirDatabase, db: &impl HirDatabase,
krate: Crate, source_root_id: SourceRootId,
) -> Cancelable<Arc<CrateImplBlocks>> { module_id: ModuleId,
let mut result = CrateImplBlocks::new(); ) -> Cancelable<Arc<ModuleImplBlocks>> {
let root_module = if let Some(root) = krate.root_module(db)? { let mut result = ModuleImplBlocks::new();
root let module = Module::new(db, source_root_id, module_id)?;
} else { result.collect(db, module)?;
return Ok(Arc::new(result));
};
result.collect(db, root_module)?;
Ok(Arc::new(result)) Ok(Arc::new(result))
} }