diff options
author | Aleksey Kladov <[email protected]> | 2019-11-27 19:12:09 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-11-27 19:12:09 +0000 |
commit | 8d3469682681d5b206d5ae31fc63fb97d9cedb3a (patch) | |
tree | e575e72ac9a441b5f9d6112087dab201e9a506ac | |
parent | 27b362b05910c81fd5b28f6cd5d2c075311032f9 (diff) |
Memoize impl resolutions
-rw-r--r-- | crates/ra_hir_ty/src/db.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/coerce.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/path.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 35 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 30 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 34 |
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}; | |||
11 | use crate::{ | 11 | use 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 | ||
7 | use hir_def::{ | 7 | use 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 | }; | ||
13 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
14 | use test_utils::tested_by; | 9 | use test_utils::tested_by; |
15 | 10 | ||
16 | use crate::{autoderef, db::HirDatabase, Substs, TraitRef, Ty, TypeCtor, TypeWalk}; | 11 | use crate::{autoderef, db::HirDatabase, ImplTy, Substs, Ty, TypeCtor, TypeWalk}; |
17 | 12 | ||
18 | use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; | 13 | use 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 | ||
3 | use hir_def::{ | 3 | use 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 | }; |
8 | use hir_expand::name::Name; | 8 | use 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)] | ||
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 | |||
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 | }; |
20 | use ra_arena::map::ArenaMap; | 20 | use ra_arena::map::ArenaMap; |
21 | use ra_db::CrateId; | 21 | use ra_db::CrateId; |
22 | 22 | ||
23 | use super::{ | ||
24 | FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, | ||
25 | Ty, TypeCtor, TypeWalk, | ||
26 | }; | ||
27 | use crate::{ | 23 | use 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 | ||
34 | impl Ty { | 34 | impl 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 | |||
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 | } | ||
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 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use hir_def::{ | 8 | use 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 | }; |
12 | use hir_expand::name::Name; | 12 | use hir_expand::name::Name; |
13 | use ra_db::CrateId; | 13 | use ra_db::CrateId; |
@@ -15,14 +15,13 @@ use ra_prof::profile; | |||
15 | use rustc_hash::FxHashMap; | 15 | use rustc_hash::FxHashMap; |
16 | 16 | ||
17 | use crate::{ | 17 | use 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 | ||
24 | use 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)] |
28 | pub enum TyFingerprint { | 27 | pub 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 | |||
11 | use ra_db::CrateId; | 11 | use ra_db::CrateId; |
12 | 12 | ||
13 | use hir_def::{ | 13 | use 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 | }; |
17 | use hir_expand::name; | 17 | use hir_expand::name; |
18 | 18 | ||
@@ -20,9 +20,8 @@ use ra_db::salsa::{InternId, InternKey}; | |||
20 | 20 | ||
21 | use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; | 21 | use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; |
22 | use crate::{ | 22 | use 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()); |