diff options
author | Florian Diebold <[email protected]> | 2020-07-11 18:12:10 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2020-07-12 19:20:31 +0100 |
commit | 7e9c4d58f189d4ac3c390a6ea345f2578dd5f661 (patch) | |
tree | 737fafc82905fdda3b52d682ff2ab04bc59b93fa /crates/ra_hir_ty/src | |
parent | 00bda1cafb1086b9669000aed5703f9e6324fbd7 (diff) |
Search more efficiently for int/float impls
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 71 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 19 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 46 |
3 files changed, 118 insertions, 18 deletions
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index a45febbf7..fb4b30a13 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -6,8 +6,10 @@ use std::{iter, sync::Arc}; | |||
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use hir_def::{ | 8 | use hir_def::{ |
9 | lang_item::LangItemTarget, type_ref::Mutability, AssocContainerId, AssocItemId, FunctionId, | 9 | builtin_type::{IntBitness, Signedness}, |
10 | HasModule, ImplId, Lookup, TraitId, | 10 | lang_item::LangItemTarget, |
11 | type_ref::Mutability, | ||
12 | AssocContainerId, AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId, | ||
11 | }; | 13 | }; |
12 | use hir_expand::name::Name; | 14 | use hir_expand::name::Name; |
13 | use ra_db::CrateId; | 15 | use ra_db::CrateId; |
@@ -16,9 +18,12 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
16 | 18 | ||
17 | use super::Substs; | 19 | use super::Substs; |
18 | use crate::{ | 20 | use crate::{ |
19 | autoderef, db::HirDatabase, primitive::FloatBitness, utils::all_super_traits, ApplicationTy, | 21 | autoderef, |
20 | Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind, TypeCtor, | 22 | db::HirDatabase, |
21 | TypeWalk, | 23 | primitive::{FloatBitness, FloatTy, IntTy}, |
24 | utils::all_super_traits, | ||
25 | ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind, | ||
26 | TypeCtor, TypeWalk, | ||
22 | }; | 27 | }; |
23 | 28 | ||
24 | /// This is used as a key for indexing impls. | 29 | /// This is used as a key for indexing impls. |
@@ -39,6 +44,62 @@ impl TyFingerprint { | |||
39 | } | 44 | } |
40 | } | 45 | } |
41 | 46 | ||
47 | pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [ | ||
48 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
49 | signedness: Signedness::Unsigned, | ||
50 | bitness: IntBitness::X8, | ||
51 | })), | ||
52 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
53 | signedness: Signedness::Unsigned, | ||
54 | bitness: IntBitness::X16, | ||
55 | })), | ||
56 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
57 | signedness: Signedness::Unsigned, | ||
58 | bitness: IntBitness::X32, | ||
59 | })), | ||
60 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
61 | signedness: Signedness::Unsigned, | ||
62 | bitness: IntBitness::X64, | ||
63 | })), | ||
64 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
65 | signedness: Signedness::Unsigned, | ||
66 | bitness: IntBitness::X128, | ||
67 | })), | ||
68 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
69 | signedness: Signedness::Unsigned, | ||
70 | bitness: IntBitness::Xsize, | ||
71 | })), | ||
72 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
73 | signedness: Signedness::Signed, | ||
74 | bitness: IntBitness::X8, | ||
75 | })), | ||
76 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
77 | signedness: Signedness::Signed, | ||
78 | bitness: IntBitness::X16, | ||
79 | })), | ||
80 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
81 | signedness: Signedness::Signed, | ||
82 | bitness: IntBitness::X32, | ||
83 | })), | ||
84 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
85 | signedness: Signedness::Signed, | ||
86 | bitness: IntBitness::X64, | ||
87 | })), | ||
88 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
89 | signedness: Signedness::Signed, | ||
90 | bitness: IntBitness::X128, | ||
91 | })), | ||
92 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
93 | signedness: Signedness::Signed, | ||
94 | bitness: IntBitness::Xsize, | ||
95 | })), | ||
96 | ]; | ||
97 | |||
98 | pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [ | ||
99 | TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 })), | ||
100 | TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 })), | ||
101 | ]; | ||
102 | |||
42 | /// Trait impls defined or available in some crate. | 103 | /// Trait impls defined or available in some crate. |
43 | #[derive(Debug, Eq, PartialEq)] | 104 | #[derive(Debug, Eq, PartialEq)] |
44 | pub struct TraitImpls { | 105 | pub struct TraitImpls { |
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 85bcd0050..511ed8fe3 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -3042,7 +3042,7 @@ fn foo() { | |||
3042 | } | 3042 | } |
3043 | 3043 | ||
3044 | #[test] | 3044 | #[test] |
3045 | fn variable_kinds() { | 3045 | fn variable_kinds_1() { |
3046 | check_types( | 3046 | check_types( |
3047 | r#" | 3047 | r#" |
3048 | trait Trait<T> { fn get(self, t: T) -> T; } | 3048 | trait Trait<T> { fn get(self, t: T) -> T; } |
@@ -3058,3 +3058,20 @@ fn test() { | |||
3058 | "#, | 3058 | "#, |
3059 | ); | 3059 | ); |
3060 | } | 3060 | } |
3061 | |||
3062 | #[test] | ||
3063 | fn variable_kinds_2() { | ||
3064 | check_types( | ||
3065 | r#" | ||
3066 | trait Trait { fn get(self) -> Self; } | ||
3067 | impl Trait for u128 {} | ||
3068 | impl Trait for f32 {} | ||
3069 | fn test() { | ||
3070 | 1.get(); | ||
3071 | //^^^^^^^ u128 | ||
3072 | (1.).get(); | ||
3073 | //^^^^^^^^^^ f32 | ||
3074 | } | ||
3075 | "#, | ||
3076 | ); | ||
3077 | } | ||
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index e944c1976..c448aea65 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -14,7 +14,10 @@ use ra_db::{salsa::InternKey, CrateId}; | |||
14 | 14 | ||
15 | use super::{builtin, AssocTyValue, ChalkContext, Impl}; | 15 | use super::{builtin, AssocTyValue, ChalkContext, Impl}; |
16 | use crate::{ | 16 | use crate::{ |
17 | db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics, | 17 | db::HirDatabase, |
18 | display::HirDisplay, | ||
19 | method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, | ||
20 | utils::generics, | ||
18 | CallableDef, DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor, | 21 | CallableDef, DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor, |
19 | }; | 22 | }; |
20 | use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders}; | 23 | use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders}; |
@@ -66,16 +69,31 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
66 | &self, | 69 | &self, |
67 | trait_id: TraitId, | 70 | trait_id: TraitId, |
68 | parameters: &[GenericArg<Interner>], | 71 | parameters: &[GenericArg<Interner>], |
69 | _binders: &CanonicalVarKinds<Interner>, | 72 | binders: &CanonicalVarKinds<Interner>, |
70 | ) -> Vec<ImplId> { | 73 | ) -> Vec<ImplId> { |
71 | debug!("impls_for_trait {:?}", trait_id); | 74 | debug!("impls_for_trait {:?}", trait_id); |
72 | let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); | 75 | let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); |
73 | 76 | ||
74 | // FIXME use binders to look for int/float impls when necessary | ||
75 | |||
76 | let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone()); | 77 | let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone()); |
77 | 78 | ||
79 | fn binder_kind(ty: &Ty, binders: &CanonicalVarKinds<Interner>) -> Option<chalk_ir::TyKind> { | ||
80 | if let Ty::Bound(bv) = ty { | ||
81 | let binders = binders.as_slice(&Interner); | ||
82 | if bv.debruijn == DebruijnIndex::INNERMOST { | ||
83 | if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind { | ||
84 | return Some(tk); | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | None | ||
89 | } | ||
90 | |||
78 | let self_ty_fp = TyFingerprint::for_impl(&ty); | 91 | let self_ty_fp = TyFingerprint::for_impl(&ty); |
92 | let fps: &[TyFingerprint] = match binder_kind(&ty, binders) { | ||
93 | Some(chalk_ir::TyKind::Integer) => &ALL_INT_FPS, | ||
94 | Some(chalk_ir::TyKind::Float) => &ALL_FLOAT_FPS, | ||
95 | _ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]), | ||
96 | }; | ||
79 | 97 | ||
80 | // Note: Since we're using impls_for_trait, only impls where the trait | 98 | // Note: Since we're using impls_for_trait, only impls where the trait |
81 | // can be resolved should ever reach Chalk. `impl_datum` relies on that | 99 | // can be resolved should ever reach Chalk. `impl_datum` relies on that |
@@ -86,17 +104,21 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
86 | 104 | ||
87 | let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db); | 105 | let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db); |
88 | 106 | ||
89 | let mut result: Vec<_> = match self_ty_fp { | 107 | let mut result: Vec<_> = if fps.is_empty() { |
90 | Some(fp) => impl_maps | 108 | debug!("Unrestricted search for {:?} impls...", trait_); |
109 | impl_maps | ||
110 | .iter() | ||
111 | .flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk)) | ||
112 | .collect() | ||
113 | } else { | ||
114 | impl_maps | ||
91 | .iter() | 115 | .iter() |
92 | .flat_map(|crate_impl_defs| { | 116 | .flat_map(|crate_impl_defs| { |
93 | crate_impl_defs.for_trait_and_self_ty(trait_, fp).map(id_to_chalk) | 117 | fps.iter().flat_map(move |fp| { |
118 | crate_impl_defs.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk) | ||
119 | }) | ||
94 | }) | 120 | }) |
95 | .collect(), | 121 | .collect() |
96 | None => impl_maps | ||
97 | .iter() | ||
98 | .flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk)) | ||
99 | .collect(), | ||
100 | }; | 122 | }; |
101 | 123 | ||
102 | let arg: Option<Ty> = | 124 | let arg: Option<Ty> = |