2431: Memoize impl resolutions r=matklad a=matklad



Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2019-11-27 19:13:34 +00:00 committed by GitHub
commit 385899d2f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 76 additions and 75 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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),
}
}

View File

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

View File

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