Skip to content

Commit 8d34696

Browse files
committed
Memoize impl resolutions
1 parent 27b362b commit 8d34696

File tree

7 files changed

+76
-75
lines changed

7 files changed

+76
-75
lines changed

crates/ra_hir_ty/src/db.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use ra_db::{salsa, CrateId};
1111
use crate::{
1212
method_resolution::CrateImplBlocks,
1313
traits::{AssocTyValue, Impl},
14-
CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, Ty, TyDefId, TypeCtor,
14+
CallableDef, FnSig, GenericPredicate, ImplTy, InferenceResult, Substs, Ty, TyDefId, TypeCtor,
1515
ValueTyDefId,
1616
};
1717

@@ -27,6 +27,9 @@ pub trait HirDatabase: DefDatabase {
2727
#[salsa::invoke(crate::lower::value_ty_query)]
2828
fn value_ty(&self, def: ValueTyDefId) -> Ty;
2929

30+
#[salsa::invoke(crate::lower::impl_ty_query)]
31+
fn impl_ty(&self, def: ImplId) -> ImplTy;
32+
3033
#[salsa::invoke(crate::lower::field_types_query)]
3134
fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>;
3235

crates/ra_hir_ty/src/infer/coerce.rs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,11 @@
44
//!
55
//! See: https://doc.rust-lang.org/nomicon/coercions.html
66
7-
use hir_def::{
8-
lang_item::LangItemTarget,
9-
resolver::{HasResolver, Resolver},
10-
type_ref::Mutability,
11-
AdtId,
12-
};
7+
use hir_def::{lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AdtId};
138
use rustc_hash::FxHashMap;
149
use test_utils::tested_by;
1510

16-
use crate::{autoderef, db::HirDatabase, Substs, TraitRef, Ty, TypeCtor, TypeWalk};
11+
use crate::{autoderef, db::HirDatabase, ImplTy, Substs, Ty, TypeCtor, TypeWalk};
1712

1813
use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue};
1914

@@ -59,17 +54,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
5954
impls
6055
.iter()
6156
.filter_map(|&impl_id| {
62-
let impl_data = db.impl_data(impl_id);
63-
let resolver = impl_id.resolver(db);
64-
let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type);
57+
let trait_ref = match db.impl_ty(impl_id) {
58+
ImplTy::TraitRef(it) => it,
59+
ImplTy::Inherent(_) => return None,
60+
};
6561

6662
// `CoerseUnsized` has one generic parameter for the target type.
67-
let trait_ref = TraitRef::from_hir(
68-
db,
69-
&resolver,
70-
impl_data.target_trait.as_ref()?,
71-
Some(target_ty),
72-
)?;
7363
let cur_from_ty = trait_ref.substs.0.get(0)?;
7464
let cur_to_ty = trait_ref.substs.0.get(1)?;
7565

crates/ra_hir_ty/src/infer/path.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use hir_def::{
44
path::{Path, PathKind, PathSegment},
5-
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
5+
resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
66
AssocItemId, ContainerId, Lookup,
77
};
88
use hir_expand::name::Name;
@@ -244,17 +244,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
244244
ContainerId::ImplId(it) => it,
245245
_ => return None,
246246
};
247-
let resolver = impl_id.resolver(self.db);
248-
let impl_data = self.db.impl_data(impl_id);
249-
let impl_block = Ty::from_hir(self.db, &resolver, &impl_data.target_type);
250-
let impl_block_substs = impl_block.substs()?;
247+
let self_ty = self.db.impl_ty(impl_id).self_type().clone();
248+
let self_ty_substs = self_ty.substs()?;
251249
let actual_substs = actual_def_ty.substs()?;
252250

253251
let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()];
254252

255253
// The following code *link up* the function actual parma type
256254
// and impl_block type param index
257-
impl_block_substs.iter().zip(actual_substs.iter()).for_each(|(param, pty)| {
255+
self_ty_substs.iter().zip(actual_substs.iter()).for_each(|(param, pty)| {
258256
if let Ty::Param { idx, .. } = param {
259257
if let Some(s) = new_substs.get_mut(*idx as usize) {
260258
*s = pty.clone();

crates/ra_hir_ty/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,21 @@ impl TypeWalk for TraitRef {
486486
}
487487
}
488488

489+
#[derive(Clone, PartialEq, Eq, Debug)]
490+
pub enum ImplTy {
491+
Inherent(Ty),
492+
TraitRef(TraitRef),
493+
}
494+
495+
impl ImplTy {
496+
pub(crate) fn self_type(&self) -> &Ty {
497+
match self {
498+
ImplTy::Inherent(it) => it,
499+
ImplTy::TraitRef(tr) => &tr.substs[0],
500+
}
501+
}
502+
}
503+
489504
/// Like `generics::WherePredicate`, but with resolved types: A condition on the
490505
/// parameters of a generic item.
491506
#[derive(Debug, Clone, PartialEq, Eq, Hash)]

crates/ra_hir_ty/src/lower.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,21 @@ use hir_def::{
1414
path::{GenericArg, Path, PathKind, PathSegment},
1515
resolver::{HasResolver, Resolver, TypeNs},
1616
type_ref::{TypeBound, TypeRef},
17-
AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule,
17+
AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
1818
LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
1919
};
2020
use ra_arena::map::ArenaMap;
2121
use ra_db::CrateId;
2222

23-
use super::{
24-
FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef,
25-
Ty, TypeCtor, TypeWalk,
26-
};
2723
use crate::{
2824
db::HirDatabase,
2925
primitive::{FloatTy, IntTy},
30-
utils::make_mut_slice,
31-
utils::{all_super_traits, associated_type_by_name_including_super_traits, variant_data},
26+
utils::{
27+
all_super_traits, associated_type_by_name_including_super_traits, make_mut_slice,
28+
variant_data,
29+
},
30+
FnSig, GenericPredicate, ImplTy, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment,
31+
TraitRef, Ty, TypeCtor, TypeWalk,
3232
};
3333

3434
impl Ty {
@@ -179,11 +179,7 @@ impl Ty {
179179
let name = resolved_segment.name.clone();
180180
Ty::Param { idx, name }
181181
}
182-
TypeNs::SelfType(impl_id) => {
183-
let impl_data = db.impl_data(impl_id);
184-
let resolver = impl_id.resolver(db);
185-
Ty::from_hir(db, &resolver, &impl_data.target_type)
186-
}
182+
TypeNs::SelfType(impl_id) => db.impl_ty(impl_id).self_type().clone(),
187183
TypeNs::AdtSelfType(adt) => db.ty(adt.into()),
188184

189185
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 {
751747
ValueTyDefId::StaticId(it) => type_for_static(db, it),
752748
}
753749
}
750+
751+
pub(crate) fn impl_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> ImplTy {
752+
let impl_data = db.impl_data(impl_id);
753+
let resolver = impl_id.resolver(db);
754+
let self_ty = Ty::from_hir(db, &resolver, &impl_data.target_type);
755+
match impl_data.target_trait.as_ref() {
756+
Some(trait_ref) => {
757+
match TraitRef::from_hir(db, &resolver, trait_ref, Some(self_ty.clone())) {
758+
Some(it) => ImplTy::TraitRef(it),
759+
None => ImplTy::Inherent(self_ty),
760+
}
761+
}
762+
None => ImplTy::Inherent(self_ty),
763+
}
764+
}

crates/ra_hir_ty/src/method_resolution.rs

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,22 @@ use std::sync::Arc;
66

77
use arrayvec::ArrayVec;
88
use hir_def::{
9-
lang_item::LangItemTarget, resolver::HasResolver, resolver::Resolver, type_ref::Mutability,
10-
AssocItemId, AstItemDef, FunctionId, HasModule, ImplId, TraitId,
9+
lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef,
10+
FunctionId, HasModule, ImplId, TraitId,
1111
};
1212
use hir_expand::name::Name;
1313
use ra_db::CrateId;
1414
use ra_prof::profile;
1515
use rustc_hash::FxHashMap;
1616

1717
use crate::{
18+
autoderef,
1819
db::HirDatabase,
1920
primitive::{FloatBitness, Uncertain},
2021
utils::all_super_traits,
21-
Ty, TypeCtor,
22+
Canonical, ImplTy, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor,
2223
};
2324

24-
use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef};
25-
2625
/// This is used as a key for indexing impls.
2726
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2827
pub enum TyFingerprint {
@@ -59,22 +58,13 @@ impl CrateImplBlocks {
5958
let crate_def_map = db.crate_def_map(krate);
6059
for (_module_id, module_data) in crate_def_map.modules.iter() {
6160
for &impl_id in module_data.impls.iter() {
62-
let impl_data = db.impl_data(impl_id);
63-
let resolver = impl_id.resolver(db);
64-
65-
let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type);
66-
67-
match &impl_data.target_trait {
68-
Some(trait_ref) => {
69-
if let Some(tr) =
70-
TraitRef::from_hir(db, &resolver, &trait_ref, Some(target_ty))
71-
{
72-
res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
73-
}
61+
match db.impl_ty(impl_id) {
62+
ImplTy::TraitRef(tr) => {
63+
res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
7464
}
75-
None => {
76-
if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
77-
res.impls.entry(target_ty_fp).or_default().push(impl_id);
65+
ImplTy::Inherent(self_ty) => {
66+
if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty) {
67+
res.impls.entry(self_ty_fp).or_default().push(impl_id);
7868
}
7969
}
8070
}

crates/ra_hir_ty/src/traits/chalk.rs

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,17 @@ use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum
1111
use ra_db::CrateId;
1212

1313
use hir_def::{
14-
expr::Expr, lang_item::LangItemTarget, resolver::HasResolver, AssocItemId, AstItemDef,
15-
ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId,
14+
expr::Expr, lang_item::LangItemTarget, AssocItemId, AstItemDef, ContainerId, GenericDefId,
15+
ImplId, Lookup, TraitId, TypeAliasId,
1616
};
1717
use hir_expand::name;
1818

1919
use ra_db::salsa::{InternId, InternKey};
2020

2121
use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
2222
use crate::{
23-
db::HirDatabase,
24-
display::HirDisplay,
25-
{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk},
23+
db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ImplTy, ProjectionTy,
24+
Substs, TraitRef, Ty, TypeCtor, TypeWalk,
2625
};
2726

2827
/// This represents a trait whose name we could not resolve.
@@ -631,13 +630,11 @@ fn impl_block_datum(
631630
chalk_id: chalk_ir::ImplId,
632631
impl_id: ImplId,
633632
) -> Option<Arc<ImplDatum<ChalkIr>>> {
633+
let trait_ref = match db.impl_ty(impl_id) {
634+
ImplTy::TraitRef(it) => it,
635+
ImplTy::Inherent(_) => return None,
636+
};
634637
let impl_data = db.impl_data(impl_id);
635-
let resolver = impl_id.resolver(db);
636-
let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type);
637-
638-
// `CoerseUnsized` has one generic parameter for the target type.
639-
let trait_ref =
640-
TraitRef::from_hir(db, &resolver, impl_data.target_trait.as_ref()?, Some(target_ty))?;
641638

642639
let generic_params = db.generic_params(impl_id.into());
643640
let bound_vars = Substs::bound_vars(&generic_params);
@@ -790,17 +787,14 @@ fn type_alias_associated_ty_value(
790787
_ => panic!("assoc ty value should be in impl"),
791788
};
792789

793-
let impl_data = db.impl_data(impl_id);
794-
let resolver = impl_id.resolver(db);
795-
let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type);
796-
let target_trait = impl_data
797-
.target_trait
798-
.as_ref()
799-
.and_then(|trait_ref| TraitRef::from_hir(db, &resolver, &trait_ref, Some(target_ty)))
800-
.expect("assoc ty value should not exist"); // we don't return any assoc ty values if the impl'd trait can't be resolved
790+
let trait_ref = match db.impl_ty(impl_id) {
791+
ImplTy::TraitRef(it) => it,
792+
// we don't return any assoc ty values if the impl'd trait can't be resolved
793+
ImplTy::Inherent(_) => panic!("assoc ty value should not exist"),
794+
};
801795

802796
let assoc_ty = db
803-
.trait_data(target_trait.trait_)
797+
.trait_data(trait_ref.trait_)
804798
.associated_type_by_name(&type_alias_data.name)
805799
.expect("assoc ty value should not exist"); // validated when building the impl data as well
806800
let generic_params = db.generic_params(impl_id.into());

0 commit comments

Comments
 (0)