use hir_ty::{
autoderef,
display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter},
- method_resolution, to_assoc_type_id,
+ method_resolution::{self, TyFingerprint},
+ to_assoc_type_id,
traits::{FnTrait, Solution, SolutionVariables},
AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate,
InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, Ty,
def_crates.iter().for_each(|&id| {
all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter))
});
+ let fp = TyFingerprint::for_impl(&ty.value);
for id in def_crates
.iter()
.flat_map(|&id| Crate { id }.reverse_dependencies(db))
.map(|Crate { id }| id)
.chain(def_crates.iter().copied())
{
- all.extend(db.trait_impls_in_crate(id).all_impls().map(Self::from).filter(filter));
+ match fp {
+ Some(fp) => all.extend(
+ db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter),
+ ),
+ None => all
+ .extend(db.trait_impls_in_crate(id).all_impls().map(Self::from).filter(filter)),
+ }
}
all
}
/// Creates a TyFingerprint for looking up an impl. Only certain types can
/// have impls: if we have some `struct S`, we can have an `impl S`, but not
/// `impl &S`. Hence, this will return `None` for reference types and such.
- pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
+ pub fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
let fp = match *ty.interned(&Interner) {
TyKind::Str => TyFingerprint::Str,
TyKind::Never => TyFingerprint::Never,
}
}
+ /// Queries all trait impls for the given type.
+ pub fn for_self_ty(&self, fp: TyFingerprint) -> impl Iterator<Item = ImplId> + '_ {
+ self.map
+ .values()
+ .flat_map(move |impls| impls.get(&None).into_iter().chain(impls.get(&Some(fp))))
+ .flat_map(|it| it.iter().copied())
+ }
+
/// Queries all impls of the given trait.
pub fn for_trait(&self, trait_: TraitId) -> impl Iterator<Item = ImplId> + '_ {
self.map