Merge #2431
2431: Memoize impl resolutions r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
385899d2f0
@ -11,7 +11,7 @@ use ra_db::{salsa, CrateId};
|
||||
use crate::{
|
||||
method_resolution::CrateImplBlocks,
|
||||
traits::{AssocTyValue, Impl},
|
||||
CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, Ty, TyDefId, TypeCtor,
|
||||
CallableDef, FnSig, GenericPredicate, ImplTy, InferenceResult, Substs, Ty, TyDefId, TypeCtor,
|
||||
ValueTyDefId,
|
||||
};
|
||||
|
||||
@ -27,6 +27,9 @@ pub trait HirDatabase: DefDatabase {
|
||||
#[salsa::invoke(crate::lower::value_ty_query)]
|
||||
fn value_ty(&self, def: ValueTyDefId) -> Ty;
|
||||
|
||||
#[salsa::invoke(crate::lower::impl_ty_query)]
|
||||
fn impl_ty(&self, def: ImplId) -> ImplTy;
|
||||
|
||||
#[salsa::invoke(crate::lower::field_types_query)]
|
||||
fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>;
|
||||
|
||||
|
@ -4,16 +4,11 @@
|
||||
//!
|
||||
//! See: https://doc.rust-lang.org/nomicon/coercions.html
|
||||
|
||||
use hir_def::{
|
||||
lang_item::LangItemTarget,
|
||||
resolver::{HasResolver, Resolver},
|
||||
type_ref::Mutability,
|
||||
AdtId,
|
||||
};
|
||||
use hir_def::{lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AdtId};
|
||||
use rustc_hash::FxHashMap;
|
||||
use test_utils::tested_by;
|
||||
|
||||
use crate::{autoderef, db::HirDatabase, Substs, TraitRef, Ty, TypeCtor, TypeWalk};
|
||||
use crate::{autoderef, db::HirDatabase, ImplTy, Substs, Ty, TypeCtor, TypeWalk};
|
||||
|
||||
use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue};
|
||||
|
||||
@ -59,17 +54,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
impls
|
||||
.iter()
|
||||
.filter_map(|&impl_id| {
|
||||
let impl_data = db.impl_data(impl_id);
|
||||
let resolver = impl_id.resolver(db);
|
||||
let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type);
|
||||
let trait_ref = match db.impl_ty(impl_id) {
|
||||
ImplTy::TraitRef(it) => it,
|
||||
ImplTy::Inherent(_) => return None,
|
||||
};
|
||||
|
||||
// `CoerseUnsized` has one generic parameter for the target type.
|
||||
let trait_ref = TraitRef::from_hir(
|
||||
db,
|
||||
&resolver,
|
||||
impl_data.target_trait.as_ref()?,
|
||||
Some(target_ty),
|
||||
)?;
|
||||
let cur_from_ty = trait_ref.substs.0.get(0)?;
|
||||
let cur_to_ty = trait_ref.substs.0.get(1)?;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use hir_def::{
|
||||
path::{Path, PathKind, PathSegment},
|
||||
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
|
||||
resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
|
||||
AssocItemId, ContainerId, Lookup,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
@ -244,17 +244,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
ContainerId::ImplId(it) => it,
|
||||
_ => return None,
|
||||
};
|
||||
let resolver = impl_id.resolver(self.db);
|
||||
let impl_data = self.db.impl_data(impl_id);
|
||||
let impl_block = Ty::from_hir(self.db, &resolver, &impl_data.target_type);
|
||||
let impl_block_substs = impl_block.substs()?;
|
||||
let self_ty = self.db.impl_ty(impl_id).self_type().clone();
|
||||
let self_ty_substs = self_ty.substs()?;
|
||||
let actual_substs = actual_def_ty.substs()?;
|
||||
|
||||
let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()];
|
||||
|
||||
// The following code *link up* the function actual parma type
|
||||
// and impl_block type param index
|
||||
impl_block_substs.iter().zip(actual_substs.iter()).for_each(|(param, pty)| {
|
||||
self_ty_substs.iter().zip(actual_substs.iter()).for_each(|(param, pty)| {
|
||||
if let Ty::Param { idx, .. } = param {
|
||||
if let Some(s) = new_substs.get_mut(*idx as usize) {
|
||||
*s = pty.clone();
|
||||
|
@ -486,6 +486,21 @@ impl TypeWalk for TraitRef {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub enum ImplTy {
|
||||
Inherent(Ty),
|
||||
TraitRef(TraitRef),
|
||||
}
|
||||
|
||||
impl ImplTy {
|
||||
pub(crate) fn self_type(&self) -> &Ty {
|
||||
match self {
|
||||
ImplTy::Inherent(it) => it,
|
||||
ImplTy::TraitRef(tr) => &tr.substs[0],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Like `generics::WherePredicate`, but with resolved types: A condition on the
|
||||
/// parameters of a generic item.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
|
@ -14,21 +14,21 @@ use hir_def::{
|
||||
path::{GenericArg, Path, PathKind, PathSegment},
|
||||
resolver::{HasResolver, Resolver, TypeNs},
|
||||
type_ref::{TypeBound, TypeRef},
|
||||
AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule,
|
||||
AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
|
||||
LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
|
||||
};
|
||||
use ra_arena::map::ArenaMap;
|
||||
use ra_db::CrateId;
|
||||
|
||||
use super::{
|
||||
FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef,
|
||||
Ty, TypeCtor, TypeWalk,
|
||||
};
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
primitive::{FloatTy, IntTy},
|
||||
utils::make_mut_slice,
|
||||
utils::{all_super_traits, associated_type_by_name_including_super_traits, variant_data},
|
||||
utils::{
|
||||
all_super_traits, associated_type_by_name_including_super_traits, make_mut_slice,
|
||||
variant_data,
|
||||
},
|
||||
FnSig, GenericPredicate, ImplTy, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment,
|
||||
TraitRef, Ty, TypeCtor, TypeWalk,
|
||||
};
|
||||
|
||||
impl Ty {
|
||||
@ -179,11 +179,7 @@ impl Ty {
|
||||
let name = resolved_segment.name.clone();
|
||||
Ty::Param { idx, name }
|
||||
}
|
||||
TypeNs::SelfType(impl_id) => {
|
||||
let impl_data = db.impl_data(impl_id);
|
||||
let resolver = impl_id.resolver(db);
|
||||
Ty::from_hir(db, &resolver, &impl_data.target_type)
|
||||
}
|
||||
TypeNs::SelfType(impl_id) => db.impl_ty(impl_id).self_type().clone(),
|
||||
TypeNs::AdtSelfType(adt) => db.ty(adt.into()),
|
||||
|
||||
TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()),
|
||||
@ -751,3 +747,18 @@ pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty {
|
||||
ValueTyDefId::StaticId(it) => type_for_static(db, it),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn impl_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> ImplTy {
|
||||
let impl_data = db.impl_data(impl_id);
|
||||
let resolver = impl_id.resolver(db);
|
||||
let self_ty = Ty::from_hir(db, &resolver, &impl_data.target_type);
|
||||
match impl_data.target_trait.as_ref() {
|
||||
Some(trait_ref) => {
|
||||
match TraitRef::from_hir(db, &resolver, trait_ref, Some(self_ty.clone())) {
|
||||
Some(it) => ImplTy::TraitRef(it),
|
||||
None => ImplTy::Inherent(self_ty),
|
||||
}
|
||||
}
|
||||
None => ImplTy::Inherent(self_ty),
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ use std::sync::Arc;
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use hir_def::{
|
||||
lang_item::LangItemTarget, resolver::HasResolver, resolver::Resolver, type_ref::Mutability,
|
||||
AssocItemId, AstItemDef, FunctionId, HasModule, ImplId, TraitId,
|
||||
lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef,
|
||||
FunctionId, HasModule, ImplId, TraitId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use ra_db::CrateId;
|
||||
@ -15,14 +15,13 @@ use ra_prof::profile;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use crate::{
|
||||
autoderef,
|
||||
db::HirDatabase,
|
||||
primitive::{FloatBitness, Uncertain},
|
||||
utils::all_super_traits,
|
||||
Ty, TypeCtor,
|
||||
Canonical, ImplTy, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor,
|
||||
};
|
||||
|
||||
use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef};
|
||||
|
||||
/// This is used as a key for indexing impls.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum TyFingerprint {
|
||||
@ -59,22 +58,13 @@ impl CrateImplBlocks {
|
||||
let crate_def_map = db.crate_def_map(krate);
|
||||
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);
|
||||
|
||||
let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type);
|
||||
|
||||
match &impl_data.target_trait {
|
||||
Some(trait_ref) => {
|
||||
if let Some(tr) =
|
||||
TraitRef::from_hir(db, &resolver, &trait_ref, Some(target_ty))
|
||||
{
|
||||
res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
|
||||
}
|
||||
match db.impl_ty(impl_id) {
|
||||
ImplTy::TraitRef(tr) => {
|
||||
res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
|
||||
}
|
||||
None => {
|
||||
if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
|
||||
res.impls.entry(target_ty_fp).or_default().push(impl_id);
|
||||
ImplTy::Inherent(self_ty) => {
|
||||
if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty) {
|
||||
res.impls.entry(self_ty_fp).or_default().push(impl_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum
|
||||
use ra_db::CrateId;
|
||||
|
||||
use hir_def::{
|
||||
expr::Expr, lang_item::LangItemTarget, resolver::HasResolver, AssocItemId, AstItemDef,
|
||||
ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId,
|
||||
expr::Expr, lang_item::LangItemTarget, AssocItemId, AstItemDef, ContainerId, GenericDefId,
|
||||
ImplId, Lookup, TraitId, TypeAliasId,
|
||||
};
|
||||
use hir_expand::name;
|
||||
|
||||
@ -20,9 +20,8 @@ use ra_db::salsa::{InternId, InternKey};
|
||||
|
||||
use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
display::HirDisplay,
|
||||
{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk},
|
||||
db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ImplTy, ProjectionTy,
|
||||
Substs, TraitRef, Ty, TypeCtor, TypeWalk,
|
||||
};
|
||||
|
||||
/// This represents a trait whose name we could not resolve.
|
||||
@ -631,13 +630,11 @@ fn impl_block_datum(
|
||||
chalk_id: chalk_ir::ImplId,
|
||||
impl_id: ImplId,
|
||||
) -> Option<Arc<ImplDatum<ChalkIr>>> {
|
||||
let trait_ref = match db.impl_ty(impl_id) {
|
||||
ImplTy::TraitRef(it) => it,
|
||||
ImplTy::Inherent(_) => return None,
|
||||
};
|
||||
let impl_data = db.impl_data(impl_id);
|
||||
let resolver = impl_id.resolver(db);
|
||||
let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type);
|
||||
|
||||
// `CoerseUnsized` has one generic parameter for the target type.
|
||||
let trait_ref =
|
||||
TraitRef::from_hir(db, &resolver, impl_data.target_trait.as_ref()?, Some(target_ty))?;
|
||||
|
||||
let generic_params = db.generic_params(impl_id.into());
|
||||
let bound_vars = Substs::bound_vars(&generic_params);
|
||||
@ -790,17 +787,14 @@ fn type_alias_associated_ty_value(
|
||||
_ => panic!("assoc ty value should be in impl"),
|
||||
};
|
||||
|
||||
let impl_data = db.impl_data(impl_id);
|
||||
let resolver = impl_id.resolver(db);
|
||||
let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type);
|
||||
let target_trait = impl_data
|
||||
.target_trait
|
||||
.as_ref()
|
||||
.and_then(|trait_ref| TraitRef::from_hir(db, &resolver, &trait_ref, Some(target_ty)))
|
||||
.expect("assoc ty value should not exist"); // we don't return any assoc ty values if the impl'd trait can't be resolved
|
||||
let trait_ref = match db.impl_ty(impl_id) {
|
||||
ImplTy::TraitRef(it) => it,
|
||||
// we don't return any assoc ty values if the impl'd trait can't be resolved
|
||||
ImplTy::Inherent(_) => panic!("assoc ty value should not exist"),
|
||||
};
|
||||
|
||||
let assoc_ty = db
|
||||
.trait_data(target_trait.trait_)
|
||||
.trait_data(trait_ref.trait_)
|
||||
.associated_type_by_name(&type_alias_data.name)
|
||||
.expect("assoc ty value should not exist"); // validated when building the impl data as well
|
||||
let generic_params = db.generic_params(impl_id.into());
|
||||
|
Loading…
x
Reference in New Issue
Block a user