aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-07-11 18:12:10 +0100
committerFlorian Diebold <[email protected]>2020-07-12 19:20:31 +0100
commit7e9c4d58f189d4ac3c390a6ea345f2578dd5f661 (patch)
tree737fafc82905fdda3b52d682ff2ab04bc59b93fa /crates/ra_hir_ty
parent00bda1cafb1086b9669000aed5703f9e6324fbd7 (diff)
Search more efficiently for int/float impls
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs71
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs19
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs46
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
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{ 8use 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};
12use hir_expand::name::Name; 14use hir_expand::name::Name;
13use ra_db::CrateId; 15use ra_db::CrateId;
@@ -16,9 +18,12 @@ use rustc_hash::{FxHashMap, FxHashSet};
16 18
17use super::Substs; 19use super::Substs;
18use crate::{ 20use 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
47pub(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
98pub(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)]
44pub struct TraitImpls { 105pub 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]
3045fn variable_kinds() { 3045fn variable_kinds_1() {
3046 check_types( 3046 check_types(
3047 r#" 3047 r#"
3048trait Trait<T> { fn get(self, t: T) -> T; } 3048trait Trait<T> { fn get(self, t: T) -> T; }
@@ -3058,3 +3058,20 @@ fn test() {
3058 "#, 3058 "#,
3059 ); 3059 );
3060} 3060}
3061
3062#[test]
3063fn variable_kinds_2() {
3064 check_types(
3065 r#"
3066trait Trait { fn get(self) -> Self; }
3067impl Trait for u128 {}
3068impl Trait for f32 {}
3069fn 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
15use super::{builtin, AssocTyValue, ChalkContext, Impl}; 15use super::{builtin, AssocTyValue, ChalkContext, Impl};
16use crate::{ 16use 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};
20use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders}; 23use 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> =