mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 22:54:58 +00:00
id-ify impls_in_crate_query
This commit is contained in:
parent
4c43631829
commit
45d05ed783
6 changed files with 76 additions and 58 deletions
|
@ -997,6 +997,15 @@ pub struct ImplBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImplBlock {
|
impl ImplBlock {
|
||||||
|
pub fn all_in_crate(db: &impl HirDatabase, krate: Crate) -> Vec<ImplBlock> {
|
||||||
|
let impls = db.impls_in_crate(krate.crate_id);
|
||||||
|
impls.all_impls().map(Self::from).collect()
|
||||||
|
}
|
||||||
|
pub fn for_trait(db: &impl HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplBlock> {
|
||||||
|
let impls = db.impls_in_crate(krate.crate_id);
|
||||||
|
impls.lookup_impl_blocks_for_trait(trait_).map(Self::from).collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
|
pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
|
||||||
db.impl_data(self.id).target_trait.clone()
|
db.impl_data(self.id).target_trait.clone()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use ra_arena::map::ArenaMap;
|
use ra_arena::map::ArenaMap;
|
||||||
use ra_db::salsa;
|
use ra_db::{salsa, CrateId};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ty::{
|
ty::{
|
||||||
|
@ -60,7 +60,7 @@ pub trait HirDatabase: DefDatabase {
|
||||||
fn generic_defaults(&self, def: GenericDefId) -> Substs;
|
fn generic_defaults(&self, def: GenericDefId) -> Substs;
|
||||||
|
|
||||||
#[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
|
#[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
|
||||||
fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
|
fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplBlocks>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::ty::traits::impls_for_trait_query)]
|
#[salsa::invoke(crate::ty::traits::impls_for_trait_query)]
|
||||||
fn impls_for_trait(&self, krate: Crate, trait_: Trait) -> Arc<[ImplBlock]>;
|
fn impls_for_trait(&self, krate: Crate, trait_: Trait) -> Arc<[ImplBlock]>;
|
||||||
|
|
|
@ -5,14 +5,19 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use hir_def::{lang_item::LangItemTarget, resolver::Resolver, AstItemDef, HasModule};
|
use hir_def::{
|
||||||
|
lang_item::LangItemTarget, resolver::HasResolver, resolver::Resolver, AssocItemId, AstItemDef,
|
||||||
|
HasModule, ImplId, TraitId,
|
||||||
|
};
|
||||||
|
use ra_db::CrateId;
|
||||||
|
use ra_prof::profile;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
ty::primitive::{FloatBitness, Uncertain},
|
ty::primitive::{FloatBitness, Uncertain},
|
||||||
ty::{Ty, TypeCtor},
|
ty::{Ty, TypeCtor},
|
||||||
AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait,
|
AssocItem, Crate, Function, Mutability, Name, Trait,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef};
|
use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef};
|
||||||
|
@ -37,53 +42,57 @@ impl TyFingerprint {
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct CrateImplBlocks {
|
pub struct CrateImplBlocks {
|
||||||
impls: FxHashMap<TyFingerprint, Vec<ImplBlock>>,
|
impls: FxHashMap<TyFingerprint, Vec<ImplId>>,
|
||||||
impls_by_trait: FxHashMap<Trait, Vec<ImplBlock>>,
|
impls_by_trait: FxHashMap<TraitId, Vec<ImplId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrateImplBlocks {
|
impl CrateImplBlocks {
|
||||||
pub(crate) fn impls_in_crate_query(
|
pub(crate) fn impls_in_crate_query(
|
||||||
db: &impl HirDatabase,
|
db: &impl HirDatabase,
|
||||||
krate: Crate,
|
krate: CrateId,
|
||||||
) -> Arc<CrateImplBlocks> {
|
) -> Arc<CrateImplBlocks> {
|
||||||
let mut crate_impl_blocks =
|
let _p = profile("impls_in_crate_query");
|
||||||
|
let mut res =
|
||||||
CrateImplBlocks { impls: FxHashMap::default(), impls_by_trait: FxHashMap::default() };
|
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().flatten().copied()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn lookup_impl_blocks_for_trait(&self, tr: Trait) -> impl Iterator<Item = ImplBlock> + '_ {
|
let crate_def_map = db.crate_def_map(krate);
|
||||||
self.impls_by_trait.get(&tr).into_iter().flatten().copied()
|
for (_module_id, module_data) in crate_def_map.modules.iter() {
|
||||||
}
|
for &impl_id in module_data.impls.iter() {
|
||||||
|
let impl_data = db.impl_data(impl_id);
|
||||||
|
let resolver = impl_id.resolver(db);
|
||||||
|
|
||||||
pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplBlock> + 'a {
|
let target_ty = { Ty::from_hir(db, &resolver, &impl_data.target_type) };
|
||||||
self.impls.values().chain(self.impls_by_trait.values()).flatten().copied()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) {
|
match &impl_data.target_trait {
|
||||||
for impl_block in module.impl_blocks(db) {
|
Some(trait_ref) => {
|
||||||
let target_ty = impl_block.target_ty(db);
|
if let Some(tr) =
|
||||||
|
TraitRef::from_hir(db, &resolver, &trait_ref, Some(target_ty))
|
||||||
if impl_block.target_trait(db).is_some() {
|
{
|
||||||
if let Some(tr) = impl_block.target_trait_ref(db) {
|
res.impls_by_trait.entry(tr.trait_.id).or_default().push(impl_id);
|
||||||
self.impls_by_trait.entry(tr.trait_).or_default().push(impl_block);
|
}
|
||||||
}
|
}
|
||||||
} else {
|
None => {
|
||||||
if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
|
if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
|
||||||
self.impls.entry(target_ty_fp).or_default().push(impl_block);
|
res.impls.entry(target_ty_fp).or_default().push(impl_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for child in module.children(db) {
|
Arc::new(res)
|
||||||
self.collect_recursive(db, child);
|
}
|
||||||
}
|
pub fn lookup_impl_blocks(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ {
|
||||||
|
let fingerprint = TyFingerprint::for_impl(ty);
|
||||||
|
fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lookup_impl_blocks_for_trait(&self, tr: Trait) -> impl Iterator<Item = ImplId> + '_ {
|
||||||
|
self.impls_by_trait.get(&tr.id).into_iter().flatten().copied()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a {
|
||||||
|
self.impls.values().chain(self.impls_by_trait.values()).flatten().copied()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,14 +288,14 @@ fn iterate_inherent_methods<T>(
|
||||||
mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
|
mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
for krate in def_crates(db, krate, &ty.value)? {
|
for krate in def_crates(db, krate, &ty.value)? {
|
||||||
let impls = db.impls_in_crate(krate);
|
let impls = db.impls_in_crate(krate.crate_id);
|
||||||
|
|
||||||
for impl_block in impls.lookup_impl_blocks(&ty.value) {
|
for impl_block in impls.lookup_impl_blocks(&ty.value) {
|
||||||
for item in impl_block.items(db) {
|
for &item in db.impl_data(impl_block).items.iter() {
|
||||||
if !is_valid_candidate(db, name, mode, item) {
|
if !is_valid_candidate(db, name, mode, item) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(result) = callback(&ty.value, item) {
|
if let Some(result) = callback(&ty.value, item.into()) {
|
||||||
return Some(result);
|
return Some(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,17 +308,17 @@ fn is_valid_candidate(
|
||||||
db: &impl HirDatabase,
|
db: &impl HirDatabase,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mode: LookupMode,
|
mode: LookupMode,
|
||||||
item: AssocItem,
|
item: AssocItemId,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match item {
|
match item {
|
||||||
AssocItem::Function(m) => {
|
AssocItemId::FunctionId(m) => {
|
||||||
let data = db.function_data(m.id);
|
let data = db.function_data(m);
|
||||||
name.map_or(true, |name| data.name == *name)
|
name.map_or(true, |name| &data.name == name)
|
||||||
&& (data.has_self_param || mode == LookupMode::Path)
|
&& (data.has_self_param || mode == LookupMode::Path)
|
||||||
}
|
}
|
||||||
AssocItem::Const(c) => {
|
AssocItemId::ConstId(c) => {
|
||||||
name.map_or(true, |name| Some(name) == c.name(db).as_ref())
|
let data = db.const_data(c);
|
||||||
&& (mode == LookupMode::Path)
|
name.map_or(true, |name| data.name.as_ref() == Some(name)) && (mode == LookupMode::Path)
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -344,11 +353,11 @@ impl Ty {
|
||||||
mut callback: impl FnMut(AssocItem) -> Option<T>,
|
mut callback: impl FnMut(AssocItem) -> Option<T>,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
for krate in def_crates(db, krate, &self)? {
|
for krate in def_crates(db, krate, &self)? {
|
||||||
let impls = db.impls_in_crate(krate);
|
let impls = db.impls_in_crate(krate.crate_id);
|
||||||
|
|
||||||
for impl_block in impls.lookup_impl_blocks(&self) {
|
for impl_block in impls.lookup_impl_blocks(&self) {
|
||||||
for item in impl_block.items(db) {
|
for &item in db.impl_data(impl_block).items.iter() {
|
||||||
if let Some(result) = callback(item) {
|
if let Some(result) = callback(item.into()) {
|
||||||
return Some(result);
|
return Some(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
//! FIXME: write short doc here
|
//! FIXME: write short doc here
|
||||||
|
|
||||||
pub use hir_ty::primitive::{FloatBitness, IntBitness, Signedness, FloatTy, IntTy, Uncertain};
|
pub use hir_ty::primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain};
|
||||||
|
|
|
@ -88,8 +88,8 @@ pub(crate) fn impls_for_trait_query(
|
||||||
for dep in krate.dependencies(db) {
|
for dep in krate.dependencies(db) {
|
||||||
impls.extend(db.impls_for_trait(dep.krate, trait_).iter());
|
impls.extend(db.impls_for_trait(dep.krate, trait_).iter());
|
||||||
}
|
}
|
||||||
let crate_impl_blocks = db.impls_in_crate(krate);
|
let crate_impl_blocks = db.impls_in_crate(krate.crate_id);
|
||||||
impls.extend(crate_impl_blocks.lookup_impl_blocks_for_trait(trait_));
|
impls.extend(crate_impl_blocks.lookup_impl_blocks_for_trait(trait_).map(ImplBlock::from));
|
||||||
impls.into_iter().collect()
|
impls.into_iter().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! FIXME: write short doc here
|
//! FIXME: write short doc here
|
||||||
|
|
||||||
use hir::{db::HirDatabase, ApplicationTy, FromSource, Ty, TypeCtor};
|
use hir::{ApplicationTy, FromSource, ImplBlock, Ty, TypeCtor};
|
||||||
use ra_db::SourceDatabase;
|
use ra_db::SourceDatabase;
|
||||||
use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
|
use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
|
||||||
|
|
||||||
|
@ -56,11 +56,11 @@ fn impls_for_def(
|
||||||
};
|
};
|
||||||
|
|
||||||
let krate = module.krate();
|
let krate = module.krate();
|
||||||
let impls = db.impls_in_crate(krate);
|
let impls = ImplBlock::all_in_crate(db, krate);
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
impls
|
impls
|
||||||
.all_impls()
|
.into_iter()
|
||||||
.filter(|impl_block| is_equal_for_find_impls(&ty, &impl_block.target_ty(db)))
|
.filter(|impl_block| is_equal_for_find_impls(&ty, &impl_block.target_ty(db)))
|
||||||
.map(|imp| imp.to_nav(db))
|
.map(|imp| imp.to_nav(db))
|
||||||
.collect(),
|
.collect(),
|
||||||
|
@ -77,9 +77,9 @@ fn impls_for_trait(
|
||||||
let tr = hir::Trait::from_source(db, src)?;
|
let tr = hir::Trait::from_source(db, src)?;
|
||||||
|
|
||||||
let krate = module.krate();
|
let krate = module.krate();
|
||||||
let impls = db.impls_in_crate(krate);
|
let impls = ImplBlock::for_trait(db, krate, tr);
|
||||||
|
|
||||||
Some(impls.lookup_impl_blocks_for_trait(tr).map(|imp| imp.to_nav(db)).collect())
|
Some(impls.into_iter().map(|imp| imp.to_nav(db)).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_equal_for_find_impls(original_ty: &Ty, impl_ty: &Ty) -> bool {
|
fn is_equal_for_find_impls(original_ty: &Ty, impl_ty: &Ty) -> bool {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue