From b21829f7edd71fb14911fc6ba47fe715757e415f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Nov 2019 21:28:00 +0300 Subject: Remove old impls infrastructure --- crates/ra_hir/src/code_model.rs | 25 ++- crates/ra_hir/src/db.rs | 20 +-- crates/ra_hir/src/from_id.rs | 15 +- crates/ra_hir/src/from_source.rs | 10 +- crates/ra_hir/src/impl_block.rs | 260 +++------------------------ crates/ra_hir/src/lang_item.rs | 2 +- crates/ra_hir/src/lib.rs | 6 +- crates/ra_hir/src/resolve.rs | 5 +- crates/ra_hir/src/ty/method_resolution.rs | 80 +++------ crates/ra_hir/src/ty/traits/chalk.rs | 6 +- crates/ra_hir_def/src/db.rs | 6 +- crates/ra_hir_def/src/imp.rs | 71 ++++++++ crates/ra_hir_def/src/lib.rs | 13 ++ crates/ra_ide_api/src/change.rs | 4 +- crates/ra_ide_api/src/references/classify.rs | 16 +- 15 files changed, 181 insertions(+), 358 deletions(-) create mode 100644 crates/ra_hir_def/src/imp.rs (limited to 'crates') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 078bd8609..731cc1fff 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -11,7 +11,7 @@ use hir_def::{ body::scope::ExprScopes, builtin_type::BuiltinType, type_ref::{Mutability, TypeRef}, - CrateModuleId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId, + CrateModuleId, ImplId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId, }; use hir_expand::{ diagnostics::DiagnosticSink, @@ -29,7 +29,6 @@ use crate::{ AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, TypeAliasId, }, - impl_block::ImplBlock, resolve::{Resolver, Scope, TypeNs}, traits::TraitData, ty::{InferenceResult, Namespace, TraitRef}, @@ -243,12 +242,8 @@ impl Module { } pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec { - let module_impl_blocks = db.impls_in_module(self); - module_impl_blocks - .impls - .iter() - .map(|(impl_id, _)| ImplBlock::from_id(self, impl_id)) - .collect() + let def_map = db.crate_def_map(self.id.krate); + def_map[self.id.module_id].impls.iter().copied().map(ImplBlock::from).collect() } fn with_module_id(self, module_id: CrateModuleId) -> Module { @@ -693,8 +688,7 @@ impl Function { /// The containing impl block, if this is a method. pub fn impl_block(self, db: &impl DefDatabase) -> Option { - let module_impls = db.impls_in_module(self.module(db)); - ImplBlock::containing(module_impls, self.into()) + ImplBlock::containing(db, self.into()) } /// The containing trait, if this is a trait method definition. @@ -759,8 +753,7 @@ impl Const { /// The containing impl block, if this is a method. pub fn impl_block(self, db: &impl DefDatabase) -> Option { - let module_impls = db.impls_in_module(self.module(db)); - ImplBlock::containing(module_impls, self.into()) + ImplBlock::containing(db, self.into()) } pub fn parent_trait(self, db: &impl DefDatabase) -> Option { @@ -973,8 +966,7 @@ impl TypeAlias { /// The containing impl block, if this is a method. pub fn impl_block(self, db: &impl DefDatabase) -> Option { - let module_impls = db.impls_in_module(self.module(db)); - ImplBlock::containing(module_impls, self.into()) + ImplBlock::containing(db, self.into()) } /// The containing trait, if this is a trait method definition. @@ -1137,3 +1129,8 @@ pub struct GenericParam { pub(crate) parent: GenericDef, pub(crate) idx: u32, } + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ImplBlock { + pub(crate) id: ImplId, +} diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index c60029c01..276b0774f 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -10,7 +10,6 @@ use crate::{ debug::HirDebugDatabase, generics::{GenericDef, GenericParams}, ids, - impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks}, lang_item::{LangItemTarget, LangItems}, traits::TraitData, ty::{ @@ -18,14 +17,14 @@ use crate::{ InferenceResult, Namespace, Substs, Ty, TypableDef, TypeCtor, }, type_alias::TypeAliasData, - Const, ConstData, Crate, DefWithBody, FnData, Function, Module, Static, StructField, Trait, - TypeAlias, + Const, ConstData, Crate, DefWithBody, FnData, Function, ImplBlock, Module, Static, StructField, + Trait, TypeAlias, }; pub use hir_def::db::{ BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, - EnumDataQuery, ExprScopesQuery, InternDatabase, InternDatabaseStorage, RawItemsQuery, - RawItemsWithSourceMapQuery, StructDataQuery, + EnumDataQuery, ExprScopesQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage, + RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, }; pub use hir_expand::db::{ AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, @@ -42,15 +41,6 @@ pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)] fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex; - #[salsa::invoke(ModuleImplBlocks::impls_in_module_with_source_map_query)] - fn impls_in_module_with_source_map( - &self, - module: Module, - ) -> (Arc, Arc); - - #[salsa::invoke(ModuleImplBlocks::impls_in_module_query)] - fn impls_in_module(&self, module: Module) -> Arc; - #[salsa::invoke(crate::generics::GenericParams::generic_params_query)] fn generic_params(&self, def: GenericDef) -> Arc; @@ -128,7 +118,7 @@ pub trait HirDatabase: DefDatabase + AstDatabase { #[salsa::interned] fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId; #[salsa::interned] - fn intern_impl(&self, impl_: Impl) -> ids::GlobalImplId; + fn intern_chalk_impl(&self, impl_: Impl) -> ids::GlobalImplId; #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)] fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc; diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs index 9633ef586..f2203e995 100644 --- a/crates/ra_hir/src/from_id.rs +++ b/crates/ra_hir/src/from_id.rs @@ -3,9 +3,9 @@ //! It's unclear if we need this long-term, but it's definitelly useful while we //! are splitting the hir. -use hir_def::{AdtId, DefWithBodyId, EnumVariantId, ModuleDefId}; +use hir_def::{AdtId, AssocItemId, DefWithBodyId, EnumVariantId, ModuleDefId}; -use crate::{Adt, DefWithBody, EnumVariant, ModuleDef}; +use crate::{Adt, AssocItem, DefWithBody, EnumVariant, ModuleDef}; macro_rules! from_id { ($(($id:path, $ty:path)),*) => {$( @@ -27,6 +27,7 @@ from_id![ (hir_def::StaticId, crate::Static), (hir_def::ConstId, crate::Const), (hir_def::FunctionId, crate::Function), + (hir_def::ImplId, crate::ImplBlock), (hir_expand::MacroDefId, crate::MacroDef) ]; @@ -71,3 +72,13 @@ impl From for DefWithBodyId { } } } + +impl From for AssocItem { + fn from(def: AssocItemId) -> Self { + match def { + AssocItemId::FunctionId(it) => AssocItem::Function(it.into()), + AssocItemId::TypeAliasId(it) => AssocItem::TypeAlias(it.into()), + AssocItemId::ConstId(it) => AssocItem::Const(it.into()), + } + } +} diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 7e5523c54..ec56dfa6a 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -82,14 +82,8 @@ impl FromSource for TypeAlias { impl FromSource for ImplBlock { type Ast = ast::ImplBlock; fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { - let module_src = crate::ModuleSource::from_child_node( - db, - src.file_id.original_file(db), - &src.ast.syntax(), - ); - let module = Module::from_definition(db, Source { file_id: src.file_id, ast: module_src })?; - let impls = module.impl_blocks(db); - impls.into_iter().find(|b| b.source(db) == src) + let id = from_source(db, src)?; + Some(ImplBlock { id }) } } diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index b1a014074..0c2bb8fee 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -1,88 +1,38 @@ //! FIXME: write short doc here -use rustc_hash::FxHashMap; -use std::sync::Arc; - -use hir_def::{attr::Attr, type_ref::TypeRef}; -use hir_expand::hygiene::Hygiene; -use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; -use ra_cfg::CfgOptions; -use ra_syntax::{ - ast::{self, AstNode}, - AstPtr, -}; +use hir_def::{type_ref::TypeRef, AstItemDef}; +use ra_syntax::ast::{self}; use crate::{ - code_model::{Module, ModuleSource}, db::{AstDatabase, DefDatabase, HirDatabase}, generics::HasGenericParams, - ids::LocationCtx, - ids::MacroCallLoc, resolve::Resolver, ty::Ty, - AssocItem, AstId, Const, Function, HasSource, HirFileId, MacroFileKind, Path, Source, TraitRef, - TypeAlias, + AssocItem, Crate, HasSource, ImplBlock, Module, Source, TraitRef, }; -#[derive(Debug, Default, PartialEq, Eq)] -pub struct ImplSourceMap { - map: ArenaMap>>, -} - -impl ImplSourceMap { - fn insert(&mut self, impl_id: ImplId, file_id: HirFileId, impl_block: &ast::ImplBlock) { - let source = Source { file_id, ast: AstPtr::new(impl_block) }; - self.map.insert(impl_id, source) - } - - pub fn get(&self, db: &impl AstDatabase, impl_id: ImplId) -> Source { - let src = self.map[impl_id]; - let root = src.file_syntax(db); - src.map(|ptr| ptr.to_node(&root)) - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct ImplBlock { - module: Module, - impl_id: ImplId, -} - impl HasSource for ImplBlock { type Ast = ast::ImplBlock; fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source { - let source_map = db.impls_in_module_with_source_map(self.module).1; - source_map.get(db, self.impl_id) + self.id.source(db) } } impl ImplBlock { - pub(crate) fn containing( - module_impl_blocks: Arc, - item: AssocItem, - ) -> Option { - let impl_id = *module_impl_blocks.impls_by_def.get(&item)?; - Some(ImplBlock { module: module_impl_blocks.module, impl_id }) - } - - pub(crate) fn from_id(module: Module, impl_id: ImplId) -> ImplBlock { - ImplBlock { module, impl_id } - } - - pub fn id(&self) -> ImplId { - self.impl_id - } - - pub fn module(&self) -> Module { - self.module + pub(crate) fn containing(db: &impl DefDatabase, item: AssocItem) -> Option { + let module = item.module(db); + let crate_def_map = db.crate_def_map(module.id.krate); + crate_def_map[module.id.module_id].impls.iter().copied().map(ImplBlock::from).find(|it| { + db.impl_data(it.id).items().iter().copied().map(AssocItem::from).any(|it| it == item) + }) } pub fn target_trait(&self, db: &impl DefDatabase) -> Option { - db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned() + db.impl_data(self.id).target_trait().cloned() } pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef { - db.impls_in_module(self.module).impls[self.impl_id].target_type().clone() + db.impl_data(self.id).target_type().clone() } pub fn target_ty(&self, db: &impl HirDatabase) -> Ty { @@ -95,15 +45,23 @@ impl ImplBlock { } pub fn items(&self, db: &impl DefDatabase) -> Vec { - db.impls_in_module(self.module).impls[self.impl_id].items().to_vec() + db.impl_data(self.id).items().iter().map(|it| (*it).into()).collect() } pub fn is_negative(&self, db: &impl DefDatabase) -> bool { - db.impls_in_module(self.module).impls[self.impl_id].negative + db.impl_data(self.id).is_negative() + } + + pub fn module(&self, db: &impl DefDatabase) -> Module { + self.id.module(db).into() + } + + pub fn krate(&self, db: &impl DefDatabase) -> Crate { + Crate { crate_id: self.module(db).id.krate } } pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { - let r = self.module().resolver(db); + let r = self.module(db).resolver(db); // add generic params, if present let p = self.generic_params(db); let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; @@ -111,175 +69,3 @@ impl ImplBlock { r } } - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ImplData { - target_trait: Option, - target_type: TypeRef, - items: Vec, - negative: bool, -} - -impl ImplData { - pub(crate) fn from_ast( - db: &(impl DefDatabase + AstDatabase), - file_id: HirFileId, - module: Module, - node: &ast::ImplBlock, - ) -> Self { - let target_trait = node.target_trait().map(TypeRef::from_ast); - let target_type = TypeRef::from_ast_opt(node.target_type()); - let ctx = LocationCtx::new(db, module.id, file_id); - let negative = node.is_negative(); - let items = if let Some(item_list) = node.item_list() { - item_list - .impl_items() - .map(|item_node| match item_node { - ast::ImplItem::FnDef(it) => Function { id: ctx.to_def(&it) }.into(), - ast::ImplItem::ConstDef(it) => Const { id: ctx.to_def(&it) }.into(), - ast::ImplItem::TypeAliasDef(it) => TypeAlias { id: ctx.to_def(&it) }.into(), - }) - .collect() - } else { - Vec::new() - }; - ImplData { target_trait, target_type, items, negative } - } - - pub fn target_trait(&self) -> Option<&TypeRef> { - self.target_trait.as_ref() - } - - pub fn target_type(&self) -> &TypeRef { - &self.target_type - } - - pub fn items(&self) -> &[AssocItem] { - &self.items - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct ImplId(pub RawId); -impl_arena_id!(ImplId); - -/// The 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 -/// a file is changed; as long as the impl blocks in the file don't change, -/// we don't need to do the second step again. -#[derive(Debug, PartialEq, Eq)] -pub struct ModuleImplBlocks { - pub(crate) module: Module, - pub(crate) impls: Arena, - impls_by_def: FxHashMap, -} - -impl ModuleImplBlocks { - pub(crate) fn impls_in_module_with_source_map_query( - db: &(impl DefDatabase + AstDatabase), - module: Module, - ) -> (Arc, Arc) { - let mut source_map = ImplSourceMap::default(); - let crate_graph = db.crate_graph(); - let cfg_options = crate_graph.cfg_options(module.id.krate); - - let result = ModuleImplBlocks::collect(db, cfg_options, module, &mut source_map); - (Arc::new(result), Arc::new(source_map)) - } - - pub(crate) fn impls_in_module_query( - db: &impl DefDatabase, - module: Module, - ) -> Arc { - db.impls_in_module_with_source_map(module).0 - } - - fn collect( - db: &(impl DefDatabase + AstDatabase), - cfg_options: &CfgOptions, - module: Module, - source_map: &mut ImplSourceMap, - ) -> Self { - let mut m = ModuleImplBlocks { - module, - impls: Arena::default(), - impls_by_def: FxHashMap::default(), - }; - - let src = m.module.definition_source(db); - match &src.ast { - ModuleSource::SourceFile(node) => { - m.collect_from_item_owner(db, cfg_options, source_map, node, src.file_id) - } - ModuleSource::Module(node) => { - let item_list = node.item_list().expect("inline module should have item list"); - m.collect_from_item_owner(db, cfg_options, source_map, &item_list, src.file_id) - } - }; - m - } - - fn collect_from_item_owner( - &mut self, - db: &(impl DefDatabase + AstDatabase), - cfg_options: &CfgOptions, - source_map: &mut ImplSourceMap, - owner: &dyn ast::ModuleItemOwner, - file_id: HirFileId, - ) { - let hygiene = Hygiene::new(db, file_id); - for item in owner.items_with_macros() { - match item { - ast::ItemOrMacro::Item(ast::ModuleItem::ImplBlock(impl_block_ast)) => { - let attrs = Attr::from_attrs_owner(&impl_block_ast, &hygiene); - if attrs.map_or(false, |attrs| { - attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) - }) { - continue; - } - - let impl_block = ImplData::from_ast(db, file_id, self.module, &impl_block_ast); - let id = self.impls.alloc(impl_block); - for &impl_item in &self.impls[id].items { - self.impls_by_def.insert(impl_item, id); - } - - source_map.insert(id, file_id, &impl_block_ast); - } - ast::ItemOrMacro::Item(_) => (), - ast::ItemOrMacro::Macro(macro_call) => { - let attrs = Attr::from_attrs_owner(¯o_call, &hygiene); - if attrs.map_or(false, |attrs| { - attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) - }) { - continue; - } - - //FIXME: we should really cut down on the boilerplate required to process a macro - let ast_id = AstId::new(file_id, db.ast_id_map(file_id).ast_id(¯o_call)); - if let Some(path) = - macro_call.path().and_then(|path| Path::from_src(path, &hygiene)) - { - if let Some(def) = self.module.resolver(db).resolve_path_as_macro(db, &path) - { - let call_id = db.intern_macro(MacroCallLoc { def: def.id, ast_id }); - let file_id = call_id.as_file(MacroFileKind::Items); - if let Some(item_list) = - db.parse_or_expand(file_id).and_then(ast::MacroItems::cast) - { - self.collect_from_item_owner( - db, - cfg_options, - source_map, - &item_list, - file_id, - ) - } - } - } - } - } - } - } -} diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs index e1780ed38..fa2ef8a17 100644 --- a/crates/ra_hir/src/lang_item.rs +++ b/crates/ra_hir/src/lang_item.rs @@ -25,7 +25,7 @@ impl LangItemTarget { Some(match self { LangItemTarget::Enum(e) => e.module(db).krate(), LangItemTarget::Function(f) => f.module(db).krate(), - LangItemTarget::ImplBlock(i) => i.module().krate(), + LangItemTarget::ImplBlock(i) => i.krate(db), LangItemTarget::Static(s) => s.module(db).krate(), LangItemTarget::Struct(s) => s.module(db).krate(), LangItemTarget::Trait(t) => t.module(db).krate(), diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 5ba847d35..da33c9591 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -54,12 +54,11 @@ mod test_db; #[cfg(test)] mod marks; -use hir_expand::AstId; - -use crate::{ids::MacroFileKind, resolve::Resolver}; +use crate::resolve::Resolver; pub use crate::{ adt::VariantDef, + code_model::ImplBlock, code_model::{ attrs::{AttrDef, Attrs}, docs::{DocDef, Docs, Documentation}, @@ -72,7 +71,6 @@ pub use crate::{ from_source::FromSource, generics::GenericDef, ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile}, - impl_block::ImplBlock, resolve::ScopeDef, source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, ty::{ diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 2fb913108..79b92180a 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs @@ -15,9 +15,8 @@ use crate::{ db::{DefDatabase, HirDatabase}, expr::{ExprScopes, PatId, ScopeId}, generics::GenericParams, - impl_block::ImplBlock, - Adt, Const, DefWithBody, Enum, EnumVariant, Function, Local, MacroDef, ModuleDef, PerNs, - Static, Struct, Trait, TypeAlias, + Adt, Const, DefWithBody, Enum, EnumVariant, Function, ImplBlock, Local, MacroDef, ModuleDef, + PerNs, Static, Struct, Trait, TypeAlias, }; #[derive(Debug, Clone, Default)] diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index eb5ca6769..9aad2d3fe 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -5,16 +5,14 @@ use std::sync::Arc; use arrayvec::ArrayVec; -use hir_def::CrateModuleId; use rustc_hash::FxHashMap; use crate::{ db::HirDatabase, - impl_block::{ImplBlock, ImplId}, resolve::Resolver, ty::primitive::{FloatBitness, Uncertain}, ty::{Ty, TypeCtor}, - AssocItem, Crate, Function, Module, Mutability, Name, Trait, + AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait, }; use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; @@ -39,65 +37,46 @@ impl TyFingerprint { #[derive(Debug, PartialEq, Eq)] pub struct CrateImplBlocks { - /// To make sense of the CrateModuleIds, we need the source root. - krate: Crate, - impls: FxHashMap>, - impls_by_trait: FxHashMap>, + impls: FxHashMap>, + impls_by_trait: FxHashMap>, } impl CrateImplBlocks { - pub fn lookup_impl_blocks<'a>(&'a self, ty: &Ty) -> impl Iterator + 'a { + pub(crate) fn impls_in_crate_query( + db: &impl HirDatabase, + krate: Crate, + ) -> Arc { + let mut crate_impl_blocks = + CrateImplBlocks { impls: FxHashMap::default(), impls_by_trait: FxHashMap::default() }; + if let Some(module) = krate.root_module(db) { + crate_impl_blocks.collect_recursive(db, module); + } + Arc::new(crate_impl_blocks) + } + pub fn lookup_impl_blocks(&self, ty: &Ty) -> impl Iterator + '_ { let fingerprint = TyFingerprint::for_impl(ty); - fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flat_map(|i| i.iter()).map( - move |(module_id, impl_id)| { - let module = Module::new(self.krate, *module_id); - ImplBlock::from_id(module, *impl_id) - }, - ) + fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied() } - pub fn lookup_impl_blocks_for_trait<'a>( - &'a self, - tr: Trait, - ) -> impl Iterator + 'a { - self.impls_by_trait.get(&tr).into_iter().flat_map(|i| i.iter()).map( - move |(module_id, impl_id)| { - let module = Module::new(self.krate, *module_id); - ImplBlock::from_id(module, *impl_id) - }, - ) + pub fn lookup_impl_blocks_for_trait(&self, tr: Trait) -> impl Iterator + '_ { + self.impls_by_trait.get(&tr).into_iter().flatten().copied() } pub fn all_impls<'a>(&'a self) -> impl Iterator + 'a { - self.impls.values().chain(self.impls_by_trait.values()).flat_map(|i| i.iter()).map( - move |(module_id, impl_id)| { - let module = Module::new(self.krate, *module_id); - ImplBlock::from_id(module, *impl_id) - }, - ) + self.impls.values().chain(self.impls_by_trait.values()).flatten().copied() } fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) { - let module_impl_blocks = db.impls_in_module(module); - - for (impl_id, _) in module_impl_blocks.impls.iter() { - let impl_block = ImplBlock::from_id(module_impl_blocks.module, impl_id); - + for impl_block in module.impl_blocks(db) { let target_ty = impl_block.target_ty(db); if impl_block.target_trait(db).is_some() { if let Some(tr) = impl_block.target_trait_ref(db) { - self.impls_by_trait - .entry(tr.trait_) - .or_insert_with(Vec::new) - .push((module.id.module_id, impl_id)); + self.impls_by_trait.entry(tr.trait_).or_default().push(impl_block); } } else { if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { - self.impls - .entry(target_ty_fp) - .or_insert_with(Vec::new) - .push((module.id.module_id, impl_id)); + self.impls.entry(target_ty_fp).or_default().push(impl_block); } } } @@ -106,21 +85,6 @@ impl CrateImplBlocks { self.collect_recursive(db, child); } } - - pub(crate) fn impls_in_crate_query( - db: &impl HirDatabase, - krate: Crate, - ) -> Arc { - let mut crate_impl_blocks = CrateImplBlocks { - krate, - impls: FxHashMap::default(), - impls_by_trait: FxHashMap::default(), - }; - if let Some(module) = krate.root_module(db) { - crate_impl_blocks.collect_recursive(db, module); - } - Arc::new(crate_impl_blocks) - } } fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option> { diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 75351c17d..68304b950 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs @@ -191,11 +191,11 @@ impl ToChalk for Impl { type Chalk = chalk_ir::ImplId; fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ImplId { - db.intern_impl(self).into() + db.intern_chalk_impl(self).into() } fn from_chalk(db: &impl HirDatabase, impl_id: chalk_ir::ImplId) -> Impl { - db.lookup_intern_impl(impl_id.into()) + db.lookup_intern_chalk_impl(impl_id.into()) } } @@ -630,7 +630,7 @@ fn impl_block_datum( .target_trait_ref(db) .expect("FIXME handle unresolved impl block trait ref") .subst(&bound_vars); - let impl_type = if impl_block.module().krate() == krate { + let impl_type = if impl_block.krate(db) == krate { chalk_rust_ir::ImplType::Local } else { chalk_rust_ir::ImplType::External diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index 40e68a3c3..348aca07f 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -8,11 +8,12 @@ use ra_syntax::ast; use crate::{ adt::{EnumData, StructData}, body::{scope::ExprScopes, Body, BodySourceMap}, + imp::ImplData, nameres::{ raw::{ImportSourceMap, RawItems}, CrateDefMap, }, - DefWithBodyId, EnumId, ItemLoc, StructOrUnionId, + DefWithBodyId, EnumId, ImplId, ItemLoc, StructOrUnionId, }; #[salsa::query_group(InternDatabaseStorage)] @@ -55,6 +56,9 @@ pub trait DefDatabase2: InternDatabase + AstDatabase { #[salsa::invoke(EnumData::enum_data_query)] fn enum_data(&self, e: EnumId) -> Arc; + #[salsa::invoke(ImplData::impl_data_query)] + fn impl_data(&self, e: ImplId) -> Arc; + #[salsa::invoke(Body::body_with_source_map_query)] fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc, Arc); diff --git a/crates/ra_hir_def/src/imp.rs b/crates/ra_hir_def/src/imp.rs new file mode 100644 index 000000000..717991c40 --- /dev/null +++ b/crates/ra_hir_def/src/imp.rs @@ -0,0 +1,71 @@ +//! Defines hir-level representation of impls. +//! +//! The handling is similar, but is not quite the same as for other items, +//! because `impl`s don't have names. + +use std::sync::Arc; + +use ra_syntax::ast; + +use crate::{ + db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, FunctionId, ImplId, + LocationCtx, TypeAliasId, +}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ImplData { + target_trait: Option, + target_type: TypeRef, + items: Vec, + negative: bool, +} + +impl ImplData { + pub(crate) fn impl_data_query(db: &impl DefDatabase2, id: ImplId) -> Arc { + let src = id.source(db); + let items = db.ast_id_map(src.file_id); + + let target_trait = src.ast.target_trait().map(TypeRef::from_ast); + let target_type = TypeRef::from_ast_opt(src.ast.target_type()); + let negative = src.ast.is_negative(); + + let items = if let Some(item_list) = src.ast.item_list() { + let ctx = LocationCtx::new(db, id.module(db), src.file_id); + item_list + .impl_items() + .map(|item_node| match item_node { + ast::ImplItem::FnDef(it) => { + FunctionId::from_ast_id(ctx, items.ast_id(&it)).into() + } + ast::ImplItem::ConstDef(it) => { + ConstId::from_ast_id(ctx, items.ast_id(&it)).into() + } + ast::ImplItem::TypeAliasDef(it) => { + TypeAliasId::from_ast_id(ctx, items.ast_id(&it)).into() + } + }) + .collect() + } else { + Vec::new() + }; + + let res = ImplData { target_trait, target_type, items, negative }; + Arc::new(res) + } + + pub fn target_trait(&self) -> Option<&TypeRef> { + self.target_trait.as_ref() + } + + pub fn target_type(&self) -> &TypeRef { + &self.target_type + } + + pub fn items(&self) -> &[AssocItemId] { + &self.items + } + + pub fn is_negative(&self) -> bool { + self.negative + } +} diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 22650db8b..0a59c4ad7 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -13,6 +13,7 @@ pub mod path; pub mod type_ref; pub mod builtin_type; pub mod adt; +pub mod imp; pub mod diagnostics; pub mod expr; pub mod body; @@ -396,3 +397,15 @@ pub enum DefWithBodyId { } impl_froms!(DefWithBodyId: FunctionId, ConstId, StaticId); + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum AssocItemId { + FunctionId(FunctionId), + ConstId(ConstId), + TypeAliasId(TypeAliasId), +} +// FIXME: not every function, ... is actually an assoc item. maybe we should make +// sure that you can only turn actual assoc items into AssocItemIds. This would +// require not implementing From, and instead having some checked way of +// casting them, and somehow making the constructors private, which would be annoying. +impl_froms!(AssocItemId: FunctionId, ConstId, TypeAliasId); diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs index 010b45141..5c9dec13e 100644 --- a/crates/ra_ide_api/src/change.rs +++ b/crates/ra_ide_api/src/change.rs @@ -271,7 +271,6 @@ impl RootDatabase { self.query(hir::db::AstIdMapQuery).sweep(sweep); self.query(hir::db::RawItemsWithSourceMapQuery).sweep(sweep); - self.query(hir::db::ImplsInModuleWithSourceMapQuery).sweep(sweep); self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep); self.query(hir::db::ExprScopesQuery).sweep(sweep); @@ -314,8 +313,6 @@ impl RootDatabase { hir::db::RawItemsWithSourceMapQuery hir::db::RawItemsQuery hir::db::CrateDefMapQuery - hir::db::ImplsInModuleWithSourceMapQuery - hir::db::ImplsInModuleQuery hir::db::GenericParamsQuery hir::db::FnDataQuery hir::db::TypeAliasDataQuery @@ -340,6 +337,7 @@ impl RootDatabase { hir::db::TraitDatumQuery hir::db::StructDatumQuery hir::db::ImplDatumQuery + hir::db::ImplDataQuery hir::db::TraitSolveQuery ]; acc.sort_by_key(|it| std::cmp::Reverse(it.1)); diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index 217f9951e..00690e449 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs @@ -114,8 +114,6 @@ pub(crate) fn classify_name_ref( file_id: FileId, name_ref: &ast::NameRef, ) -> Option { - use PathResolution::*; - let _p = profile("classify_name_ref"); let parent = name_ref.syntax().parent()?; @@ -163,26 +161,26 @@ pub(crate) fn classify_name_ref( let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; let resolved = analyzer.resolve_path(db, &path)?; match resolved { - Def(def) => Some(from_module_def(db, def, Some(container))), - AssocItem(item) => Some(from_assoc_item(db, item)), - Local(local) => { + PathResolution::Def(def) => Some(from_module_def(db, def, Some(container))), + PathResolution::AssocItem(item) => Some(from_assoc_item(db, item)), + PathResolution::Local(local) => { let container = local.module(db); let kind = NameKind::Local(local); Some(NameDefinition { kind, container, visibility: None }) } - GenericParam(par) => { + PathResolution::GenericParam(par) => { // FIXME: get generic param def let kind = NameKind::GenericParam(par); Some(NameDefinition { kind, container, visibility }) } - Macro(def) => { + PathResolution::Macro(def) => { let kind = NameKind::Macro(def); Some(NameDefinition { kind, container, visibility }) } - SelfType(impl_block) => { + PathResolution::SelfType(impl_block) => { let ty = impl_block.target_ty(db); let kind = NameKind::SelfType(ty); - let container = impl_block.module(); + let container = impl_block.module(db); Some(NameDefinition { kind, container, visibility }) } } -- cgit v1.2.3