Remove old impls infrastructure

This commit is contained in:
Aleksey Kladov 2019-11-15 21:28:00 +03:00
parent ea3540c1a8
commit b21829f7ed
15 changed files with 181 additions and 358 deletions

View file

@ -11,7 +11,7 @@ use hir_def::{
body::scope::ExprScopes, body::scope::ExprScopes,
builtin_type::BuiltinType, builtin_type::BuiltinType,
type_ref::{Mutability, TypeRef}, type_ref::{Mutability, TypeRef},
CrateModuleId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId, CrateModuleId, ImplId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId,
}; };
use hir_expand::{ use hir_expand::{
diagnostics::DiagnosticSink, diagnostics::DiagnosticSink,
@ -29,7 +29,6 @@ use crate::{
AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId,
TypeAliasId, TypeAliasId,
}, },
impl_block::ImplBlock,
resolve::{Resolver, Scope, TypeNs}, resolve::{Resolver, Scope, TypeNs},
traits::TraitData, traits::TraitData,
ty::{InferenceResult, Namespace, TraitRef}, ty::{InferenceResult, Namespace, TraitRef},
@ -243,12 +242,8 @@ impl Module {
} }
pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> { pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> {
let module_impl_blocks = db.impls_in_module(self); let def_map = db.crate_def_map(self.id.krate);
module_impl_blocks def_map[self.id.module_id].impls.iter().copied().map(ImplBlock::from).collect()
.impls
.iter()
.map(|(impl_id, _)| ImplBlock::from_id(self, impl_id))
.collect()
} }
fn with_module_id(self, module_id: CrateModuleId) -> Module { fn with_module_id(self, module_id: CrateModuleId) -> Module {
@ -693,8 +688,7 @@ impl Function {
/// The containing impl block, if this is a method. /// The containing impl block, if this is a method.
pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
let module_impls = db.impls_in_module(self.module(db)); ImplBlock::containing(db, self.into())
ImplBlock::containing(module_impls, self.into())
} }
/// The containing trait, if this is a trait method definition. /// 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. /// The containing impl block, if this is a method.
pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
let module_impls = db.impls_in_module(self.module(db)); ImplBlock::containing(db, self.into())
ImplBlock::containing(module_impls, self.into())
} }
pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> { pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
@ -973,8 +966,7 @@ impl TypeAlias {
/// The containing impl block, if this is a method. /// The containing impl block, if this is a method.
pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
let module_impls = db.impls_in_module(self.module(db)); ImplBlock::containing(db, self.into())
ImplBlock::containing(module_impls, self.into())
} }
/// The containing trait, if this is a trait method definition. /// The containing trait, if this is a trait method definition.
@ -1137,3 +1129,8 @@ pub struct GenericParam {
pub(crate) parent: GenericDef, pub(crate) parent: GenericDef,
pub(crate) idx: u32, pub(crate) idx: u32,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ImplBlock {
pub(crate) id: ImplId,
}

View file

@ -10,7 +10,6 @@ use crate::{
debug::HirDebugDatabase, debug::HirDebugDatabase,
generics::{GenericDef, GenericParams}, generics::{GenericDef, GenericParams},
ids, ids,
impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks},
lang_item::{LangItemTarget, LangItems}, lang_item::{LangItemTarget, LangItems},
traits::TraitData, traits::TraitData,
ty::{ ty::{
@ -18,14 +17,14 @@ use crate::{
InferenceResult, Namespace, Substs, Ty, TypableDef, TypeCtor, InferenceResult, Namespace, Substs, Ty, TypableDef, TypeCtor,
}, },
type_alias::TypeAliasData, type_alias::TypeAliasData,
Const, ConstData, Crate, DefWithBody, FnData, Function, Module, Static, StructField, Trait, Const, ConstData, Crate, DefWithBody, FnData, Function, ImplBlock, Module, Static, StructField,
TypeAlias, Trait, TypeAlias,
}; };
pub use hir_def::db::{ pub use hir_def::db::{
BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage,
EnumDataQuery, ExprScopesQuery, InternDatabase, InternDatabaseStorage, RawItemsQuery, EnumDataQuery, ExprScopesQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage,
RawItemsWithSourceMapQuery, StructDataQuery, RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery,
}; };
pub use hir_expand::db::{ pub use hir_expand::db::{
AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
@ -42,15 +41,6 @@ pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
#[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)] #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)]
fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex; 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<ModuleImplBlocks>, Arc<ImplSourceMap>);
#[salsa::invoke(ModuleImplBlocks::impls_in_module_query)]
fn impls_in_module(&self, module: Module) -> Arc<ModuleImplBlocks>;
#[salsa::invoke(crate::generics::GenericParams::generic_params_query)] #[salsa::invoke(crate::generics::GenericParams::generic_params_query)]
fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>; fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>;
@ -128,7 +118,7 @@ pub trait HirDatabase: DefDatabase + AstDatabase {
#[salsa::interned] #[salsa::interned]
fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId; fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId;
#[salsa::interned] #[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)] #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)]
fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc<chalk_rust_ir::AssociatedTyDatum>; fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc<chalk_rust_ir::AssociatedTyDatum>;

View file

@ -3,9 +3,9 @@
//! It's unclear if we need this long-term, but it's definitelly useful while we //! It's unclear if we need this long-term, but it's definitelly useful while we
//! are splitting the hir. //! 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 { macro_rules! from_id {
($(($id:path, $ty:path)),*) => {$( ($(($id:path, $ty:path)),*) => {$(
@ -27,6 +27,7 @@ from_id![
(hir_def::StaticId, crate::Static), (hir_def::StaticId, crate::Static),
(hir_def::ConstId, crate::Const), (hir_def::ConstId, crate::Const),
(hir_def::FunctionId, crate::Function), (hir_def::FunctionId, crate::Function),
(hir_def::ImplId, crate::ImplBlock),
(hir_expand::MacroDefId, crate::MacroDef) (hir_expand::MacroDefId, crate::MacroDef)
]; ];
@ -71,3 +72,13 @@ impl From<DefWithBody> for DefWithBodyId {
} }
} }
} }
impl From<AssocItemId> 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()),
}
}
}

View file

@ -82,14 +82,8 @@ impl FromSource for TypeAlias {
impl FromSource for ImplBlock { impl FromSource for ImplBlock {
type Ast = ast::ImplBlock; type Ast = ast::ImplBlock;
fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
let module_src = crate::ModuleSource::from_child_node( let id = from_source(db, src)?;
db, Some(ImplBlock { id })
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)
} }
} }

View file

@ -1,88 +1,38 @@
//! FIXME: write short doc here //! FIXME: write short doc here
use rustc_hash::FxHashMap; use hir_def::{type_ref::TypeRef, AstItemDef};
use std::sync::Arc; use ra_syntax::ast::{self};
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 crate::{ use crate::{
code_model::{Module, ModuleSource},
db::{AstDatabase, DefDatabase, HirDatabase}, db::{AstDatabase, DefDatabase, HirDatabase},
generics::HasGenericParams, generics::HasGenericParams,
ids::LocationCtx,
ids::MacroCallLoc,
resolve::Resolver, resolve::Resolver,
ty::Ty, ty::Ty,
AssocItem, AstId, Const, Function, HasSource, HirFileId, MacroFileKind, Path, Source, TraitRef, AssocItem, Crate, HasSource, ImplBlock, Module, Source, TraitRef,
TypeAlias,
}; };
#[derive(Debug, Default, PartialEq, Eq)]
pub struct ImplSourceMap {
map: ArenaMap<ImplId, Source<AstPtr<ast::ImplBlock>>>,
}
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<ast::ImplBlock> {
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 { impl HasSource for ImplBlock {
type Ast = ast::ImplBlock; type Ast = ast::ImplBlock;
fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::ImplBlock> { fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::ImplBlock> {
let source_map = db.impls_in_module_with_source_map(self.module).1; self.id.source(db)
source_map.get(db, self.impl_id)
} }
} }
impl ImplBlock { impl ImplBlock {
pub(crate) fn containing( pub(crate) fn containing(db: &impl DefDatabase, item: AssocItem) -> Option<ImplBlock> {
module_impl_blocks: Arc<ModuleImplBlocks>, let module = item.module(db);
item: AssocItem, let crate_def_map = db.crate_def_map(module.id.krate);
) -> Option<ImplBlock> { crate_def_map[module.id.module_id].impls.iter().copied().map(ImplBlock::from).find(|it| {
let impl_id = *module_impl_blocks.impls_by_def.get(&item)?; db.impl_data(it.id).items().iter().copied().map(AssocItem::from).any(|it| it == 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 fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> { pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
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 { 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 { pub fn target_ty(&self, db: &impl HirDatabase) -> Ty {
@ -95,15 +45,23 @@ impl ImplBlock {
} }
pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> { pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> {
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 { 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 { 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 // add generic params, if present
let p = self.generic_params(db); let p = self.generic_params(db);
let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
@ -111,175 +69,3 @@ impl ImplBlock {
r r
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImplData {
target_trait: Option<TypeRef>,
target_type: TypeRef,
items: Vec<AssocItem>,
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<ImplId, ImplData>,
impls_by_def: FxHashMap<AssocItem, ImplId>,
}
impl ModuleImplBlocks {
pub(crate) fn impls_in_module_with_source_map_query(
db: &(impl DefDatabase + AstDatabase),
module: Module,
) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) {
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<ModuleImplBlocks> {
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(&macro_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(&macro_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,
)
}
}
}
}
}
}
}
}

View file

@ -25,7 +25,7 @@ impl LangItemTarget {
Some(match self { Some(match self {
LangItemTarget::Enum(e) => e.module(db).krate(), LangItemTarget::Enum(e) => e.module(db).krate(),
LangItemTarget::Function(f) => f.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::Static(s) => s.module(db).krate(),
LangItemTarget::Struct(s) => s.module(db).krate(), LangItemTarget::Struct(s) => s.module(db).krate(),
LangItemTarget::Trait(t) => t.module(db).krate(), LangItemTarget::Trait(t) => t.module(db).krate(),

View file

@ -54,12 +54,11 @@ mod test_db;
#[cfg(test)] #[cfg(test)]
mod marks; mod marks;
use hir_expand::AstId; use crate::resolve::Resolver;
use crate::{ids::MacroFileKind, resolve::Resolver};
pub use crate::{ pub use crate::{
adt::VariantDef, adt::VariantDef,
code_model::ImplBlock,
code_model::{ code_model::{
attrs::{AttrDef, Attrs}, attrs::{AttrDef, Attrs},
docs::{DocDef, Docs, Documentation}, docs::{DocDef, Docs, Documentation},
@ -72,7 +71,6 @@ pub use crate::{
from_source::FromSource, from_source::FromSource,
generics::GenericDef, generics::GenericDef,
ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile}, ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile},
impl_block::ImplBlock,
resolve::ScopeDef, resolve::ScopeDef,
source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
ty::{ ty::{

View file

@ -15,9 +15,8 @@ use crate::{
db::{DefDatabase, HirDatabase}, db::{DefDatabase, HirDatabase},
expr::{ExprScopes, PatId, ScopeId}, expr::{ExprScopes, PatId, ScopeId},
generics::GenericParams, generics::GenericParams,
impl_block::ImplBlock, Adt, Const, DefWithBody, Enum, EnumVariant, Function, ImplBlock, Local, MacroDef, ModuleDef,
Adt, Const, DefWithBody, Enum, EnumVariant, Function, Local, MacroDef, ModuleDef, PerNs, PerNs, Static, Struct, Trait, TypeAlias,
Static, Struct, Trait, TypeAlias,
}; };
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]

View file

@ -5,16 +5,14 @@
use std::sync::Arc; use std::sync::Arc;
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use hir_def::CrateModuleId;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use crate::{ use crate::{
db::HirDatabase, db::HirDatabase,
impl_block::{ImplBlock, ImplId},
resolve::Resolver, resolve::Resolver,
ty::primitive::{FloatBitness, Uncertain}, ty::primitive::{FloatBitness, Uncertain},
ty::{Ty, TypeCtor}, 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}; use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef};
@ -39,65 +37,46 @@ impl TyFingerprint {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct CrateImplBlocks { pub struct CrateImplBlocks {
/// To make sense of the CrateModuleIds, we need the source root. impls: FxHashMap<TyFingerprint, Vec<ImplBlock>>,
krate: Crate, impls_by_trait: FxHashMap<Trait, Vec<ImplBlock>>,
impls: FxHashMap<TyFingerprint, Vec<(CrateModuleId, ImplId)>>,
impls_by_trait: FxHashMap<Trait, Vec<(CrateModuleId, ImplId)>>,
} }
impl CrateImplBlocks { impl CrateImplBlocks {
pub fn lookup_impl_blocks<'a>(&'a self, ty: &Ty) -> impl Iterator<Item = ImplBlock> + 'a { pub(crate) fn impls_in_crate_query(
db: &impl HirDatabase,
krate: Crate,
) -> Arc<CrateImplBlocks> {
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<Item = ImplBlock> + '_ {
let fingerprint = TyFingerprint::for_impl(ty); let fingerprint = TyFingerprint::for_impl(ty);
fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flat_map(|i| i.iter()).map( fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied()
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<'a>( pub fn lookup_impl_blocks_for_trait(&self, tr: Trait) -> impl Iterator<Item = ImplBlock> + '_ {
&'a self, self.impls_by_trait.get(&tr).into_iter().flatten().copied()
tr: Trait,
) -> impl Iterator<Item = ImplBlock> + '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 all_impls<'a>(&'a self) -> impl Iterator<Item = ImplBlock> + 'a { pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplBlock> + 'a {
self.impls.values().chain(self.impls_by_trait.values()).flat_map(|i| i.iter()).map( self.impls.values().chain(self.impls_by_trait.values()).flatten().copied()
move |(module_id, impl_id)| {
let module = Module::new(self.krate, *module_id);
ImplBlock::from_id(module, *impl_id)
},
)
} }
fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) { fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) {
let module_impl_blocks = db.impls_in_module(module); for impl_block in module.impl_blocks(db) {
for (impl_id, _) in module_impl_blocks.impls.iter() {
let impl_block = ImplBlock::from_id(module_impl_blocks.module, impl_id);
let target_ty = impl_block.target_ty(db); let target_ty = impl_block.target_ty(db);
if impl_block.target_trait(db).is_some() { if impl_block.target_trait(db).is_some() {
if let Some(tr) = impl_block.target_trait_ref(db) { if let Some(tr) = impl_block.target_trait_ref(db) {
self.impls_by_trait self.impls_by_trait.entry(tr.trait_).or_default().push(impl_block);
.entry(tr.trait_)
.or_insert_with(Vec::new)
.push((module.id.module_id, impl_id));
} }
} else { } else {
if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
self.impls self.impls.entry(target_ty_fp).or_default().push(impl_block);
.entry(target_ty_fp)
.or_insert_with(Vec::new)
.push((module.id.module_id, impl_id));
} }
} }
} }
@ -106,21 +85,6 @@ impl CrateImplBlocks {
self.collect_recursive(db, child); self.collect_recursive(db, child);
} }
} }
pub(crate) fn impls_in_crate_query(
db: &impl HirDatabase,
krate: Crate,
) -> Arc<CrateImplBlocks> {
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<ArrayVec<[Crate; 2]>> { fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> {

View file

@ -191,11 +191,11 @@ impl ToChalk for Impl {
type Chalk = chalk_ir::ImplId; type Chalk = chalk_ir::ImplId;
fn to_chalk(self, db: &impl HirDatabase) -> 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 { 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) .target_trait_ref(db)
.expect("FIXME handle unresolved impl block trait ref") .expect("FIXME handle unresolved impl block trait ref")
.subst(&bound_vars); .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 chalk_rust_ir::ImplType::Local
} else { } else {
chalk_rust_ir::ImplType::External chalk_rust_ir::ImplType::External

View file

@ -8,11 +8,12 @@ use ra_syntax::ast;
use crate::{ use crate::{
adt::{EnumData, StructData}, adt::{EnumData, StructData},
body::{scope::ExprScopes, Body, BodySourceMap}, body::{scope::ExprScopes, Body, BodySourceMap},
imp::ImplData,
nameres::{ nameres::{
raw::{ImportSourceMap, RawItems}, raw::{ImportSourceMap, RawItems},
CrateDefMap, CrateDefMap,
}, },
DefWithBodyId, EnumId, ItemLoc, StructOrUnionId, DefWithBodyId, EnumId, ImplId, ItemLoc, StructOrUnionId,
}; };
#[salsa::query_group(InternDatabaseStorage)] #[salsa::query_group(InternDatabaseStorage)]
@ -55,6 +56,9 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
#[salsa::invoke(EnumData::enum_data_query)] #[salsa::invoke(EnumData::enum_data_query)]
fn enum_data(&self, e: EnumId) -> Arc<EnumData>; fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
#[salsa::invoke(ImplData::impl_data_query)]
fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
#[salsa::invoke(Body::body_with_source_map_query)] #[salsa::invoke(Body::body_with_source_map_query)]
fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>); fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);

View file

@ -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<TypeRef>,
target_type: TypeRef,
items: Vec<AssocItemId>,
negative: bool,
}
impl ImplData {
pub(crate) fn impl_data_query(db: &impl DefDatabase2, id: ImplId) -> Arc<ImplData> {
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
}
}

View file

@ -13,6 +13,7 @@ pub mod path;
pub mod type_ref; pub mod type_ref;
pub mod builtin_type; pub mod builtin_type;
pub mod adt; pub mod adt;
pub mod imp;
pub mod diagnostics; pub mod diagnostics;
pub mod expr; pub mod expr;
pub mod body; pub mod body;
@ -396,3 +397,15 @@ pub enum DefWithBodyId {
} }
impl_froms!(DefWithBodyId: FunctionId, ConstId, StaticId); 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);

View file

@ -271,7 +271,6 @@ impl RootDatabase {
self.query(hir::db::AstIdMapQuery).sweep(sweep); self.query(hir::db::AstIdMapQuery).sweep(sweep);
self.query(hir::db::RawItemsWithSourceMapQuery).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::BodyWithSourceMapQuery).sweep(sweep);
self.query(hir::db::ExprScopesQuery).sweep(sweep); self.query(hir::db::ExprScopesQuery).sweep(sweep);
@ -314,8 +313,6 @@ impl RootDatabase {
hir::db::RawItemsWithSourceMapQuery hir::db::RawItemsWithSourceMapQuery
hir::db::RawItemsQuery hir::db::RawItemsQuery
hir::db::CrateDefMapQuery hir::db::CrateDefMapQuery
hir::db::ImplsInModuleWithSourceMapQuery
hir::db::ImplsInModuleQuery
hir::db::GenericParamsQuery hir::db::GenericParamsQuery
hir::db::FnDataQuery hir::db::FnDataQuery
hir::db::TypeAliasDataQuery hir::db::TypeAliasDataQuery
@ -340,6 +337,7 @@ impl RootDatabase {
hir::db::TraitDatumQuery hir::db::TraitDatumQuery
hir::db::StructDatumQuery hir::db::StructDatumQuery
hir::db::ImplDatumQuery hir::db::ImplDatumQuery
hir::db::ImplDataQuery
hir::db::TraitSolveQuery hir::db::TraitSolveQuery
]; ];
acc.sort_by_key(|it| std::cmp::Reverse(it.1)); acc.sort_by_key(|it| std::cmp::Reverse(it.1));

View file

@ -114,8 +114,6 @@ pub(crate) fn classify_name_ref(
file_id: FileId, file_id: FileId,
name_ref: &ast::NameRef, name_ref: &ast::NameRef,
) -> Option<NameDefinition> { ) -> Option<NameDefinition> {
use PathResolution::*;
let _p = profile("classify_name_ref"); let _p = profile("classify_name_ref");
let parent = name_ref.syntax().parent()?; 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 path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
let resolved = analyzer.resolve_path(db, &path)?; let resolved = analyzer.resolve_path(db, &path)?;
match resolved { match resolved {
Def(def) => Some(from_module_def(db, def, Some(container))), PathResolution::Def(def) => Some(from_module_def(db, def, Some(container))),
AssocItem(item) => Some(from_assoc_item(db, item)), PathResolution::AssocItem(item) => Some(from_assoc_item(db, item)),
Local(local) => { PathResolution::Local(local) => {
let container = local.module(db); let container = local.module(db);
let kind = NameKind::Local(local); let kind = NameKind::Local(local);
Some(NameDefinition { kind, container, visibility: None }) Some(NameDefinition { kind, container, visibility: None })
} }
GenericParam(par) => { PathResolution::GenericParam(par) => {
// FIXME: get generic param def // FIXME: get generic param def
let kind = NameKind::GenericParam(par); let kind = NameKind::GenericParam(par);
Some(NameDefinition { kind, container, visibility }) Some(NameDefinition { kind, container, visibility })
} }
Macro(def) => { PathResolution::Macro(def) => {
let kind = NameKind::Macro(def); let kind = NameKind::Macro(def);
Some(NameDefinition { kind, container, visibility }) Some(NameDefinition { kind, container, visibility })
} }
SelfType(impl_block) => { PathResolution::SelfType(impl_block) => {
let ty = impl_block.target_ty(db); let ty = impl_block.target_ty(db);
let kind = NameKind::SelfType(ty); let kind = NameKind::SelfType(ty);
let container = impl_block.module(); let container = impl_block.module(db);
Some(NameDefinition { kind, container, visibility }) Some(NameDefinition { kind, container, visibility })
} }
} }