mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Remove old impls infrastructure
This commit is contained in:
parent
ea3540c1a8
commit
b21829f7ed
15 changed files with 181 additions and 358 deletions
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(¯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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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::{
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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]>> {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>);
|
||||
|
||||
|
|
71
crates/ra_hir_def/src/imp.rs
Normal file
71
crates/ra_hir_def/src/imp.rs
Normal 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
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 })
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue