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,
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<ImplBlock> {
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<ImplBlock> {
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<ImplBlock> {
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<Trait> {
@ -973,8 +966,7 @@ impl TypeAlias {
/// The containing impl block, if this is a method.
pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
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,
}

View file

@ -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<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)]
fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>;
@ -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<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
//! 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<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 {
type Ast = ast::ImplBlock;
fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
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 })
}
}

View file

@ -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<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 {
type Ast = 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;
source_map.get(db, self.impl_id)
self.id.source(db)
}
}
impl ImplBlock {
pub(crate) fn containing(
module_impl_blocks: Arc<ModuleImplBlocks>,
item: AssocItem,
) -> Option<ImplBlock> {
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<ImplBlock> {
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<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 {
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<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 {
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<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 {
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(),

View file

@ -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::{

View file

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

View file

@ -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<TyFingerprint, Vec<(CrateModuleId, ImplId)>>,
impls_by_trait: FxHashMap<Trait, Vec<(CrateModuleId, ImplId)>>,
impls: FxHashMap<TyFingerprint, Vec<ImplBlock>>,
impls_by_trait: FxHashMap<Trait, Vec<ImplBlock>>,
}
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);
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<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 lookup_impl_blocks_for_trait(&self, tr: Trait) -> impl Iterator<Item = ImplBlock> + '_ {
self.impls_by_trait.get(&tr).into_iter().flatten().copied()
}
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(
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<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]>> {

View file

@ -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

View file

@ -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<EnumData>;
#[salsa::invoke(ImplData::impl_data_query)]
fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
#[salsa::invoke(Body::body_with_source_map_query)]
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 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);

View file

@ -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));

View file

@ -114,8 +114,6 @@ pub(crate) fn classify_name_ref(
file_id: FileId,
name_ref: &ast::NameRef,
) -> Option<NameDefinition> {
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 })
}
}