Skip to content

Commit 7e9c4d5

Browse files
committed
Search more efficiently for int/float impls
1 parent 00bda1c commit 7e9c4d5

File tree

3 files changed

+118
-18
lines changed

3 files changed

+118
-18
lines changed

crates/ra_hir_ty/src/method_resolution.rs

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ use std::{iter, sync::Arc};
66

77
use arrayvec::ArrayVec;
88
use hir_def::{
9-
lang_item::LangItemTarget, type_ref::Mutability, AssocContainerId, AssocItemId, FunctionId,
10-
HasModule, ImplId, Lookup, TraitId,
9+
builtin_type::{IntBitness, Signedness},
10+
lang_item::LangItemTarget,
11+
type_ref::Mutability,
12+
AssocContainerId, AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId,
1113
};
1214
use hir_expand::name::Name;
1315
use ra_db::CrateId;
@@ -16,9 +18,12 @@ use rustc_hash::{FxHashMap, FxHashSet};
1618

1719
use super::Substs;
1820
use crate::{
19-
autoderef, db::HirDatabase, primitive::FloatBitness, utils::all_super_traits, ApplicationTy,
20-
Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind, TypeCtor,
21-
TypeWalk,
21+
autoderef,
22+
db::HirDatabase,
23+
primitive::{FloatBitness, FloatTy, IntTy},
24+
utils::all_super_traits,
25+
ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind,
26+
TypeCtor, TypeWalk,
2227
};
2328

2429
/// This is used as a key for indexing impls.
@@ -39,6 +44,62 @@ impl TyFingerprint {
3944
}
4045
}
4146

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+
42103
/// Trait impls defined or available in some crate.
43104
#[derive(Debug, Eq, PartialEq)]
44105
pub struct TraitImpls {

crates/ra_hir_ty/src/tests/traits.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3042,7 +3042,7 @@ fn foo() {
30423042
}
30433043

30443044
#[test]
3045-
fn variable_kinds() {
3045+
fn variable_kinds_1() {
30463046
check_types(
30473047
r#"
30483048
trait Trait<T> { fn get(self, t: T) -> T; }
@@ -3058,3 +3058,20 @@ fn test() {
30583058
"#,
30593059
);
30603060
}
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+
}

crates/ra_hir_ty/src/traits/chalk.rs

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ use ra_db::{salsa::InternKey, CrateId};
1414

1515
use super::{builtin, AssocTyValue, ChalkContext, Impl};
1616
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,
1821
CallableDef, DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor,
1922
};
2023
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> {
6669
&self,
6770
trait_id: TraitId,
6871
parameters: &[GenericArg<Interner>],
69-
_binders: &CanonicalVarKinds<Interner>,
72+
binders: &CanonicalVarKinds<Interner>,
7073
) -> Vec<ImplId> {
7174
debug!("impls_for_trait {:?}", trait_id);
7275
let trait_: hir_def::TraitId = from_chalk(self.db, trait_id);
7376

74-
// FIXME use binders to look for int/float impls when necessary
75-
7677
let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone());
7778

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+
7891
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+
};
7997

8098
// Note: Since we're using impls_for_trait, only impls where the trait
8199
// 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> {
86104

87105
let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db);
88106

89-
let mut result: Vec<_> = match self_ty_fp {
90-
Some(fp) => impl_maps
107+
let mut result: Vec<_> = if fps.is_empty() {
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
91115
.iter()
92116
.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+
})
94120
})
95-
.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(),
121+
.collect()
100122
};
101123

102124
let arg: Option<Ty> =

0 commit comments

Comments
 (0)