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::{ use crate::{
method_resolution::CrateImplBlocks, method_resolution::CrateImplBlocks,
traits::{AssocTyValue, Impl}, traits::{AssocTyValue, Impl},
CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, Ty, TyDefId, TypeCtor, CallableDef, FnSig, GenericPredicate, ImplTy, InferenceResult, Substs, Ty, TyDefId, TypeCtor,
ValueTyDefId, ValueTyDefId,
}; };
@ -27,6 +27,9 @@ pub trait HirDatabase: DefDatabase {
#[salsa::invoke(crate::lower::value_ty_query)] #[salsa::invoke(crate::lower::value_ty_query)]
fn value_ty(&self, def: ValueTyDefId) -> Ty; 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)] #[salsa::invoke(crate::lower::field_types_query)]
fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>; 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 //! See: https://doc.rust-lang.org/nomicon/coercions.html
use hir_def::{ use hir_def::{lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AdtId};
lang_item::LangItemTarget,
resolver::{HasResolver, Resolver},
type_ref::Mutability,
AdtId,
};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use test_utils::tested_by; 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}; use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue};
@ -59,17 +54,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
impls impls
.iter() .iter()
.filter_map(|&impl_id| { .filter_map(|&impl_id| {
let impl_data = db.impl_data(impl_id); let trait_ref = match db.impl_ty(impl_id) {
let resolver = impl_id.resolver(db); ImplTy::TraitRef(it) => it,
let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type); ImplTy::Inherent(_) => return None,
};
// `CoerseUnsized` has one generic parameter for the 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 cur_from_ty = trait_ref.substs.0.get(0)?; let cur_from_ty = trait_ref.substs.0.get(0)?;
let cur_to_ty = trait_ref.substs.0.get(1)?; let cur_to_ty = trait_ref.substs.0.get(1)?;

View file

@ -2,7 +2,7 @@
use hir_def::{ use hir_def::{
path::{Path, PathKind, PathSegment}, path::{Path, PathKind, PathSegment},
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs}, resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
AssocItemId, ContainerId, Lookup, AssocItemId, ContainerId, Lookup,
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
@ -244,17 +244,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
ContainerId::ImplId(it) => it, ContainerId::ImplId(it) => it,
_ => return None, _ => return None,
}; };
let resolver = impl_id.resolver(self.db); let self_ty = self.db.impl_ty(impl_id).self_type().clone();
let impl_data = self.db.impl_data(impl_id); let self_ty_substs = self_ty.substs()?;
let impl_block = Ty::from_hir(self.db, &resolver, &impl_data.target_type);
let impl_block_substs = impl_block.substs()?;
let actual_substs = actual_def_ty.substs()?; let actual_substs = actual_def_ty.substs()?;
let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()]; let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()];
// The following code *link up* the function actual parma type // The following code *link up* the function actual parma type
// and impl_block type param index // 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 Ty::Param { idx, .. } = param {
if let Some(s) = new_substs.get_mut(*idx as usize) { if let Some(s) = new_substs.get_mut(*idx as usize) {
*s = pty.clone(); *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 /// Like `generics::WherePredicate`, but with resolved types: A condition on the
/// parameters of a generic item. /// parameters of a generic item.
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]

View file

@ -14,21 +14,21 @@ use hir_def::{
path::{GenericArg, Path, PathKind, PathSegment}, path::{GenericArg, Path, PathKind, PathSegment},
resolver::{HasResolver, Resolver, TypeNs}, resolver::{HasResolver, Resolver, TypeNs},
type_ref::{TypeBound, TypeRef}, 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, LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
}; };
use ra_arena::map::ArenaMap; use ra_arena::map::ArenaMap;
use ra_db::CrateId; use ra_db::CrateId;
use super::{
FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef,
Ty, TypeCtor, TypeWalk,
};
use crate::{ use crate::{
db::HirDatabase, db::HirDatabase,
primitive::{FloatTy, IntTy}, primitive::{FloatTy, IntTy},
utils::make_mut_slice, utils::{
utils::{all_super_traits, associated_type_by_name_including_super_traits, variant_data}, 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 { impl Ty {
@ -179,11 +179,7 @@ impl Ty {
let name = resolved_segment.name.clone(); let name = resolved_segment.name.clone();
Ty::Param { idx, name } Ty::Param { idx, name }
} }
TypeNs::SelfType(impl_id) => { TypeNs::SelfType(impl_id) => db.impl_ty(impl_id).self_type().clone(),
let impl_data = db.impl_data(impl_id);
let resolver = impl_id.resolver(db);
Ty::from_hir(db, &resolver, &impl_data.target_type)
}
TypeNs::AdtSelfType(adt) => db.ty(adt.into()), TypeNs::AdtSelfType(adt) => db.ty(adt.into()),
TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.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), 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 arrayvec::ArrayVec;
use hir_def::{ use hir_def::{
lang_item::LangItemTarget, resolver::HasResolver, resolver::Resolver, type_ref::Mutability, lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef,
AssocItemId, AstItemDef, FunctionId, HasModule, ImplId, TraitId, FunctionId, HasModule, ImplId, TraitId,
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
use ra_db::CrateId; use ra_db::CrateId;
@ -15,14 +15,13 @@ use ra_prof::profile;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use crate::{ use crate::{
autoderef,
db::HirDatabase, db::HirDatabase,
primitive::{FloatBitness, Uncertain}, primitive::{FloatBitness, Uncertain},
utils::all_super_traits, 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. /// This is used as a key for indexing impls.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum TyFingerprint { pub enum TyFingerprint {
@ -59,22 +58,13 @@ impl CrateImplBlocks {
let crate_def_map = db.crate_def_map(krate); let crate_def_map = db.crate_def_map(krate);
for (_module_id, module_data) in crate_def_map.modules.iter() { for (_module_id, module_data) in crate_def_map.modules.iter() {
for &impl_id in module_data.impls.iter() { for &impl_id in module_data.impls.iter() {
let impl_data = db.impl_data(impl_id); match db.impl_ty(impl_id) {
let resolver = impl_id.resolver(db); ImplTy::TraitRef(tr) => {
res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
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);
}
} }
None => { ImplTy::Inherent(self_ty) => {
if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty) {
res.impls.entry(target_ty_fp).or_default().push(impl_id); 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 ra_db::CrateId;
use hir_def::{ use hir_def::{
expr::Expr, lang_item::LangItemTarget, resolver::HasResolver, AssocItemId, AstItemDef, expr::Expr, lang_item::LangItemTarget, AssocItemId, AstItemDef, ContainerId, GenericDefId,
ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId, ImplId, Lookup, TraitId, TypeAliasId,
}; };
use hir_expand::name; use hir_expand::name;
@ -20,9 +20,8 @@ use ra_db::salsa::{InternId, InternKey};
use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
use crate::{ use crate::{
db::HirDatabase, db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ImplTy, ProjectionTy,
display::HirDisplay, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk},
}; };
/// This represents a trait whose name we could not resolve. /// This represents a trait whose name we could not resolve.
@ -631,13 +630,11 @@ fn impl_block_datum(
chalk_id: chalk_ir::ImplId, chalk_id: chalk_ir::ImplId,
impl_id: ImplId, impl_id: ImplId,
) -> Option<Arc<ImplDatum<ChalkIr>>> { ) -> 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 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 generic_params = db.generic_params(impl_id.into());
let bound_vars = Substs::bound_vars(&generic_params); 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"), _ => panic!("assoc ty value should be in impl"),
}; };
let impl_data = db.impl_data(impl_id); let trait_ref = match db.impl_ty(impl_id) {
let resolver = impl_id.resolver(db); ImplTy::TraitRef(it) => it,
let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type); // we don't return any assoc ty values if the impl'd trait can't be resolved
let target_trait = impl_data ImplTy::Inherent(_) => panic!("assoc ty value should not exist"),
.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 assoc_ty = db let assoc_ty = db
.trait_data(target_trait.trait_) .trait_data(trait_ref.trait_)
.associated_type_by_name(&type_alias_data.name) .associated_type_by_name(&type_alias_data.name)
.expect("assoc ty value should not exist"); // validated when building the impl data as well .expect("assoc ty value should not exist"); // validated when building the impl data as well
let generic_params = db.generic_params(impl_id.into()); let generic_params = db.generic_params(impl_id.into());