aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-11-27 19:12:09 +0000
committerAleksey Kladov <[email protected]>2019-11-27 19:12:09 +0000
commit8d3469682681d5b206d5ae31fc63fb97d9cedb3a (patch)
treee575e72ac9a441b5f9d6112087dab201e9a506ac
parent27b362b05910c81fd5b28f6cd5d2c075311032f9 (diff)
Memoize impl resolutions
-rw-r--r--crates/ra_hir_ty/src/db.rs5
-rw-r--r--crates/ra_hir_ty/src/infer/coerce.rs22
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs10
-rw-r--r--crates/ra_hir_ty/src/lib.rs15
-rw-r--r--crates/ra_hir_ty/src/lower.rs35
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs30
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs34
7 files changed, 76 insertions, 75 deletions
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
index aa2659c4b..9ce154593 100644
--- a/crates/ra_hir_ty/src/db.rs
+++ b/crates/ra_hir_ty/src/db.rs
@@ -11,7 +11,7 @@ use ra_db::{salsa, CrateId};
11use crate::{ 11use crate::{
12 method_resolution::CrateImplBlocks, 12 method_resolution::CrateImplBlocks,
13 traits::{AssocTyValue, Impl}, 13 traits::{AssocTyValue, Impl},
14 CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, Ty, TyDefId, TypeCtor, 14 CallableDef, FnSig, GenericPredicate, ImplTy, InferenceResult, Substs, Ty, TyDefId, TypeCtor,
15 ValueTyDefId, 15 ValueTyDefId,
16}; 16};
17 17
@@ -27,6 +27,9 @@ pub trait HirDatabase: DefDatabase {
27 #[salsa::invoke(crate::lower::value_ty_query)] 27 #[salsa::invoke(crate::lower::value_ty_query)]
28 fn value_ty(&self, def: ValueTyDefId) -> Ty; 28 fn value_ty(&self, def: ValueTyDefId) -> Ty;
29 29
30 #[salsa::invoke(crate::lower::impl_ty_query)]
31 fn impl_ty(&self, def: ImplId) -> ImplTy;
32
30 #[salsa::invoke(crate::lower::field_types_query)] 33 #[salsa::invoke(crate::lower::field_types_query)]
31 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>; 34 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>;
32 35
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs
index d66a21932..719a0f395 100644
--- a/crates/ra_hir_ty/src/infer/coerce.rs
+++ b/crates/ra_hir_ty/src/infer/coerce.rs
@@ -4,16 +4,11 @@
4//! 4//!
5//! See: https://doc.rust-lang.org/nomicon/coercions.html 5//! See: https://doc.rust-lang.org/nomicon/coercions.html
6 6
7use hir_def::{ 7use hir_def::{lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AdtId};
8 lang_item::LangItemTarget,
9 resolver::{HasResolver, Resolver},
10 type_ref::Mutability,
11 AdtId,
12};
13use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
14use test_utils::tested_by; 9use test_utils::tested_by;
15 10
16use crate::{autoderef, db::HirDatabase, Substs, TraitRef, Ty, TypeCtor, TypeWalk}; 11use crate::{autoderef, db::HirDatabase, ImplTy, Substs, Ty, TypeCtor, TypeWalk};
17 12
18use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; 13use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue};
19 14
@@ -59,17 +54,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
59 impls 54 impls
60 .iter() 55 .iter()
61 .filter_map(|&impl_id| { 56 .filter_map(|&impl_id| {
62 let impl_data = db.impl_data(impl_id); 57 let trait_ref = match db.impl_ty(impl_id) {
63 let resolver = impl_id.resolver(db); 58 ImplTy::TraitRef(it) => it,
64 let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type); 59 ImplTy::Inherent(_) => return None,
60 };
65 61
66 // `CoerseUnsized` has one generic parameter for the target type. 62 // `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 )?;
73 let cur_from_ty = trait_ref.substs.0.get(0)?; 63 let cur_from_ty = trait_ref.substs.0.get(0)?;
74 let cur_to_ty = trait_ref.substs.0.get(1)?; 64 let cur_to_ty = trait_ref.substs.0.get(1)?;
75 65
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index e6676e1aa..14be66836 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -2,7 +2,7 @@
2 2
3use hir_def::{ 3use hir_def::{
4 path::{Path, PathKind, PathSegment}, 4 path::{Path, PathKind, PathSegment},
5 resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs}, 5 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
6 AssocItemId, ContainerId, Lookup, 6 AssocItemId, ContainerId, Lookup,
7}; 7};
8use hir_expand::name::Name; 8use hir_expand::name::Name;
@@ -244,17 +244,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
244 ContainerId::ImplId(it) => it, 244 ContainerId::ImplId(it) => it,
245 _ => return None, 245 _ => return None,
246 }; 246 };
247 let resolver = impl_id.resolver(self.db); 247 let self_ty = self.db.impl_ty(impl_id).self_type().clone();
248 let impl_data = self.db.impl_data(impl_id); 248 let self_ty_substs = self_ty.substs()?;
249 let impl_block = Ty::from_hir(self.db, &resolver, &impl_data.target_type);
250 let impl_block_substs = impl_block.substs()?;
251 let actual_substs = actual_def_ty.substs()?; 249 let actual_substs = actual_def_ty.substs()?;
252 250
253 let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()]; 251 let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()];
254 252
255 // The following code *link up* the function actual parma type 253 // The following code *link up* the function actual parma type
256 // and impl_block type param index 254 // 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)| {
258 if let Ty::Param { idx, .. } = param { 256 if let Ty::Param { idx, .. } = param {
259 if let Some(s) = new_substs.get_mut(*idx as usize) { 257 if let Some(s) = new_substs.get_mut(*idx as usize) {
260 *s = pty.clone(); 258 *s = pty.clone();
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index f25846326..c9ee34008 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -486,6 +486,21 @@ impl TypeWalk for TraitRef {
486 } 486 }
487} 487}
488 488
489#[derive(Clone, PartialEq, Eq, Debug)]
490pub enum ImplTy {
491 Inherent(Ty),
492 TraitRef(TraitRef),
493}
494
495impl 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
489/// Like `generics::WherePredicate`, but with resolved types: A condition on the 504/// Like `generics::WherePredicate`, but with resolved types: A condition on the
490/// parameters of a generic item. 505/// parameters of a generic item.
491#[derive(Debug, Clone, PartialEq, Eq, Hash)] 506#[derive(Debug, Clone, PartialEq, Eq, Hash)]
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index 53d955a12..f8331d257 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -14,21 +14,21 @@ use hir_def::{
14 path::{GenericArg, Path, PathKind, PathSegment}, 14 path::{GenericArg, Path, PathKind, PathSegment},
15 resolver::{HasResolver, Resolver, TypeNs}, 15 resolver::{HasResolver, Resolver, TypeNs},
16 type_ref::{TypeBound, TypeRef}, 16 type_ref::{TypeBound, TypeRef},
17 AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, 17 AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
18 LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, 18 LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
19}; 19};
20use ra_arena::map::ArenaMap; 20use ra_arena::map::ArenaMap;
21use ra_db::CrateId; 21use ra_db::CrateId;
22 22
23use super::{
24 FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef,
25 Ty, TypeCtor, TypeWalk,
26};
27use crate::{ 23use crate::{
28 db::HirDatabase, 24 db::HirDatabase,
29 primitive::{FloatTy, IntTy}, 25 primitive::{FloatTy, IntTy},
30 utils::make_mut_slice, 26 utils::{
31 utils::{all_super_traits, associated_type_by_name_including_super_traits, variant_data}, 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,
32}; 32};
33 33
34impl Ty { 34impl Ty {
@@ -179,11 +179,7 @@ impl Ty {
179 let name = resolved_segment.name.clone(); 179 let name = resolved_segment.name.clone();
180 Ty::Param { idx, name } 180 Ty::Param { idx, name }
181 } 181 }
182 TypeNs::SelfType(impl_id) => { 182 TypeNs::SelfType(impl_id) => db.impl_ty(impl_id).self_type().clone(),
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 }
187 TypeNs::AdtSelfType(adt) => db.ty(adt.into()), 183 TypeNs::AdtSelfType(adt) => db.ty(adt.into()),
188 184
189 TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), 185 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 {
751 ValueTyDefId::StaticId(it) => type_for_static(db, it), 747 ValueTyDefId::StaticId(it) => type_for_static(db, it),
752 } 748 }
753} 749}
750
751pub(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}
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 53c541eb8..ee1936b0e 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -6,8 +6,8 @@ use std::sync::Arc;
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{ 8use hir_def::{
9 lang_item::LangItemTarget, resolver::HasResolver, resolver::Resolver, type_ref::Mutability, 9 lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef,
10 AssocItemId, AstItemDef, FunctionId, HasModule, ImplId, TraitId, 10 FunctionId, HasModule, ImplId, TraitId,
11}; 11};
12use hir_expand::name::Name; 12use hir_expand::name::Name;
13use ra_db::CrateId; 13use ra_db::CrateId;
@@ -15,14 +15,13 @@ use ra_prof::profile;
15use rustc_hash::FxHashMap; 15use rustc_hash::FxHashMap;
16 16
17use crate::{ 17use crate::{
18 autoderef,
18 db::HirDatabase, 19 db::HirDatabase,
19 primitive::{FloatBitness, Uncertain}, 20 primitive::{FloatBitness, Uncertain},
20 utils::all_super_traits, 21 utils::all_super_traits,
21 Ty, TypeCtor, 22 Canonical, ImplTy, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor,
22}; 23};
23 24
24use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef};
25
26/// This is used as a key for indexing impls. 25/// This is used as a key for indexing impls.
27#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 26#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
28pub enum TyFingerprint { 27pub enum TyFingerprint {
@@ -59,22 +58,13 @@ impl CrateImplBlocks {
59 let crate_def_map = db.crate_def_map(krate); 58 let crate_def_map = db.crate_def_map(krate);
60 for (_module_id, module_data) in crate_def_map.modules.iter() { 59 for (_module_id, module_data) in crate_def_map.modules.iter() {
61 for &impl_id in module_data.impls.iter() { 60 for &impl_id in module_data.impls.iter() {
62 let impl_data = db.impl_data(impl_id); 61 match db.impl_ty(impl_id) {
63 let resolver = impl_id.resolver(db); 62 ImplTy::TraitRef(tr) => {
64 63 res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
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 }
74 } 64 }
75 None => { 65 ImplTy::Inherent(self_ty) => {
76 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { 66 if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty) {
77 res.impls.entry(target_ty_fp).or_default().push(impl_id); 67 res.impls.entry(self_ty_fp).or_default().push(impl_id);
78 } 68 }
79 } 69 }
80 } 70 }
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 810e8c21a..35de37e6b 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -11,8 +11,8 @@ use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum
11use ra_db::CrateId; 11use ra_db::CrateId;
12 12
13use hir_def::{ 13use hir_def::{
14 expr::Expr, lang_item::LangItemTarget, resolver::HasResolver, AssocItemId, AstItemDef, 14 expr::Expr, lang_item::LangItemTarget, AssocItemId, AstItemDef, ContainerId, GenericDefId,
15 ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId, 15 ImplId, Lookup, TraitId, TypeAliasId,
16}; 16};
17use hir_expand::name; 17use hir_expand::name;
18 18
@@ -20,9 +20,8 @@ use ra_db::salsa::{InternId, InternKey};
20 20
21use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; 21use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
22use crate::{ 22use crate::{
23 db::HirDatabase, 23 db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ImplTy, ProjectionTy,
24 display::HirDisplay, 24 Substs, TraitRef, Ty, TypeCtor, TypeWalk,
25 {ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk},
26}; 25};
27 26
28/// This represents a trait whose name we could not resolve. 27/// This represents a trait whose name we could not resolve.
@@ -631,13 +630,11 @@ fn impl_block_datum(
631 chalk_id: chalk_ir::ImplId, 630 chalk_id: chalk_ir::ImplId,
632 impl_id: ImplId, 631 impl_id: ImplId,
633) -> Option<Arc<ImplDatum<ChalkIr>>> { 632) -> 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 };
634 let impl_data = db.impl_data(impl_id); 637 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))?;
641 638
642 let generic_params = db.generic_params(impl_id.into()); 639 let generic_params = db.generic_params(impl_id.into());
643 let bound_vars = Substs::bound_vars(&generic_params); 640 let bound_vars = Substs::bound_vars(&generic_params);
@@ -790,17 +787,14 @@ fn type_alias_associated_ty_value(
790 _ => panic!("assoc ty value should be in impl"), 787 _ => panic!("assoc ty value should be in impl"),
791 }; 788 };
792 789
793 let impl_data = db.impl_data(impl_id); 790 let trait_ref = match db.impl_ty(impl_id) {
794 let resolver = impl_id.resolver(db); 791 ImplTy::TraitRef(it) => it,
795 let target_ty = Ty::from_hir(db, &resolver, &impl_data.target_type); 792 // we don't return any assoc ty values if the impl'd trait can't be resolved
796 let target_trait = impl_data 793 ImplTy::Inherent(_) => panic!("assoc ty value should not exist"),
797 .target_trait 794 };
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
801 795
802 let assoc_ty = db 796 let assoc_ty = db
803 .trait_data(target_trait.trait_) 797 .trait_data(trait_ref.trait_)
804 .associated_type_by_name(&type_alias_data.name) 798 .associated_type_by_name(&type_alias_data.name)
805 .expect("assoc ty value should not exist"); // validated when building the impl data as well 799 .expect("assoc ty value should not exist"); // validated when building the impl data as well
806 let generic_params = db.generic_params(impl_id.into()); 800 let generic_params = db.generic_params(impl_id.into());