mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-10 15:14:32 +00:00
Search more efficiently for int/float impls
This commit is contained in:
parent
00bda1cafb
commit
7e9c4d58f1
3 changed files with 119 additions and 19 deletions
|
@ -6,8 +6,10 @@ use std::{iter, sync::Arc};
|
|||
|
||||
use arrayvec::ArrayVec;
|
||||
use hir_def::{
|
||||
lang_item::LangItemTarget, type_ref::Mutability, AssocContainerId, AssocItemId, FunctionId,
|
||||
HasModule, ImplId, Lookup, TraitId,
|
||||
builtin_type::{IntBitness, Signedness},
|
||||
lang_item::LangItemTarget,
|
||||
type_ref::Mutability,
|
||||
AssocContainerId, AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use ra_db::CrateId;
|
||||
|
@ -16,9 +18,12 @@ use rustc_hash::{FxHashMap, FxHashSet};
|
|||
|
||||
use super::Substs;
|
||||
use crate::{
|
||||
autoderef, db::HirDatabase, primitive::FloatBitness, utils::all_super_traits, ApplicationTy,
|
||||
Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind, TypeCtor,
|
||||
TypeWalk,
|
||||
autoderef,
|
||||
db::HirDatabase,
|
||||
primitive::{FloatBitness, FloatTy, IntTy},
|
||||
utils::all_super_traits,
|
||||
ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind,
|
||||
TypeCtor, TypeWalk,
|
||||
};
|
||||
|
||||
/// This is used as a key for indexing impls.
|
||||
|
@ -39,6 +44,62 @@ impl TyFingerprint {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Unsigned,
|
||||
bitness: IntBitness::X8,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Unsigned,
|
||||
bitness: IntBitness::X16,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Unsigned,
|
||||
bitness: IntBitness::X32,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Unsigned,
|
||||
bitness: IntBitness::X64,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Unsigned,
|
||||
bitness: IntBitness::X128,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Unsigned,
|
||||
bitness: IntBitness::Xsize,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Signed,
|
||||
bitness: IntBitness::X8,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Signed,
|
||||
bitness: IntBitness::X16,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Signed,
|
||||
bitness: IntBitness::X32,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Signed,
|
||||
bitness: IntBitness::X64,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Signed,
|
||||
bitness: IntBitness::X128,
|
||||
})),
|
||||
TyFingerprint::Apply(TypeCtor::Int(IntTy {
|
||||
signedness: Signedness::Signed,
|
||||
bitness: IntBitness::Xsize,
|
||||
})),
|
||||
];
|
||||
|
||||
pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [
|
||||
TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 })),
|
||||
TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 })),
|
||||
];
|
||||
|
||||
/// Trait impls defined or available in some crate.
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct TraitImpls {
|
||||
|
|
|
@ -3042,7 +3042,7 @@ fn foo() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn variable_kinds() {
|
||||
fn variable_kinds_1() {
|
||||
check_types(
|
||||
r#"
|
||||
trait Trait<T> { fn get(self, t: T) -> T; }
|
||||
|
@ -3058,3 +3058,20 @@ fn test() {
|
|||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variable_kinds_2() {
|
||||
check_types(
|
||||
r#"
|
||||
trait Trait { fn get(self) -> Self; }
|
||||
impl Trait for u128 {}
|
||||
impl Trait for f32 {}
|
||||
fn test() {
|
||||
1.get();
|
||||
//^^^^^^^ u128
|
||||
(1.).get();
|
||||
//^^^^^^^^^^ f32
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,10 @@ use ra_db::{salsa::InternKey, CrateId};
|
|||
|
||||
use super::{builtin, AssocTyValue, ChalkContext, Impl};
|
||||
use crate::{
|
||||
db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics,
|
||||
db::HirDatabase,
|
||||
display::HirDisplay,
|
||||
method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
|
||||
utils::generics,
|
||||
CallableDef, DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor,
|
||||
};
|
||||
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> {
|
|||
&self,
|
||||
trait_id: TraitId,
|
||||
parameters: &[GenericArg<Interner>],
|
||||
_binders: &CanonicalVarKinds<Interner>,
|
||||
binders: &CanonicalVarKinds<Interner>,
|
||||
) -> Vec<ImplId> {
|
||||
debug!("impls_for_trait {:?}", trait_id);
|
||||
let trait_: hir_def::TraitId = from_chalk(self.db, trait_id);
|
||||
|
||||
// FIXME use binders to look for int/float impls when necessary
|
||||
|
||||
let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone());
|
||||
|
||||
fn binder_kind(ty: &Ty, binders: &CanonicalVarKinds<Interner>) -> Option<chalk_ir::TyKind> {
|
||||
if let Ty::Bound(bv) = ty {
|
||||
let binders = binders.as_slice(&Interner);
|
||||
if bv.debruijn == DebruijnIndex::INNERMOST {
|
||||
if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind {
|
||||
return Some(tk);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
let self_ty_fp = TyFingerprint::for_impl(&ty);
|
||||
let fps: &[TyFingerprint] = match binder_kind(&ty, binders) {
|
||||
Some(chalk_ir::TyKind::Integer) => &ALL_INT_FPS,
|
||||
Some(chalk_ir::TyKind::Float) => &ALL_FLOAT_FPS,
|
||||
_ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]),
|
||||
};
|
||||
|
||||
// Note: Since we're using impls_for_trait, only impls where the trait
|
||||
// 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> {
|
|||
|
||||
let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db);
|
||||
|
||||
let mut result: Vec<_> = match self_ty_fp {
|
||||
Some(fp) => impl_maps
|
||||
.iter()
|
||||
.flat_map(|crate_impl_defs| {
|
||||
crate_impl_defs.for_trait_and_self_ty(trait_, fp).map(id_to_chalk)
|
||||
})
|
||||
.collect(),
|
||||
None => impl_maps
|
||||
let mut result: Vec<_> = if fps.is_empty() {
|
||||
debug!("Unrestricted search for {:?} impls...", trait_);
|
||||
impl_maps
|
||||
.iter()
|
||||
.flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk))
|
||||
.collect(),
|
||||
.collect()
|
||||
} else {
|
||||
impl_maps
|
||||
.iter()
|
||||
.flat_map(|crate_impl_defs| {
|
||||
fps.iter().flat_map(move |fp| {
|
||||
crate_impl_defs.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk)
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
|
||||
let arg: Option<Ty> =
|
||||
|
|
Loading…
Reference in a new issue