1
Fork 0

Rollup merge of #77754 - bugadani:find_map_relevant_impl, r=matthewjasper

Add TraitDef::find_map_relevant_impl

This PR adds a method to `TraitDef`. While `for_each_relevant_impl` covers the general use case, sometimes it's not necessary to scan through all the relevant implementations, so this PR introduces a new method, `find_map_relevant_impl`. I've also replaced the `for_each_relevant_impl` calls where possible.

I'm hoping for a tiny bit of efficiency gain here and there.
This commit is contained in:
Yuki Okushi 2020-10-11 03:19:14 +09:00 committed by GitHub
commit 8752b43900
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 27 deletions

View file

@ -123,10 +123,26 @@ impl<'tcx> TyCtxt<'tcx> {
self_ty: Ty<'tcx>,
mut f: F,
) {
let _: Option<()> = self.find_map_relevant_impl(def_id, self_ty, |did| {
f(did);
None
});
}
/// Applies function to every impl that could possibly match the self type `self_ty` and returns
/// the first non-none value.
pub fn find_map_relevant_impl<T, F: FnMut(DefId) -> Option<T>>(
self,
def_id: DefId,
self_ty: Ty<'tcx>,
mut f: F,
) -> Option<T> {
let impls = self.trait_impls_of(def_id);
for &impl_def_id in impls.blanket_impls.iter() {
f(impl_def_id);
if let result @ Some(_) = f(impl_def_id) {
return result;
}
}
// simplify_type(.., false) basically replaces type parameters and
@ -157,14 +173,20 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) {
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
for &impl_def_id in impls {
f(impl_def_id);
if let result @ Some(_) = f(impl_def_id) {
return result;
}
}
}
} else {
for &impl_def_id in impls.non_blanket_impls.values().flatten() {
f(impl_def_id);
if let result @ Some(_) = f(impl_def_id) {
return result;
}
}
}
None
}
/// Returns an iterator containing all impls

View file

@ -346,14 +346,14 @@ impl<'tcx> TyCtxt<'tcx> {
let drop_trait = self.lang_items().drop_trait()?;
self.ensure().coherent_trait(drop_trait);
let mut dtor_did = None;
let ty = self.type_of(adt_did);
self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
let dtor_did = self.find_map_relevant_impl(drop_trait, ty, |impl_did| {
if let Some(item) = self.associated_items(impl_did).in_definition_order().next() {
if validate(self, impl_did).is_ok() {
dtor_did = Some(item.def_id);
return Some(item.def_id);
}
}
None
});
Some(ty::Destructor { did: dtor_did? })

View file

@ -34,7 +34,6 @@ impl<'a, 'tcx> ConstMutationChecker<'a, 'tcx> {
fn is_const_item_without_destructor(&self, local: Local) -> Option<DefId> {
let def_id = self.is_const_item(local)?;
let mut any_dtor = |_tcx, _def_id| Ok(());
// We avoid linting mutation of a const item if the const's type has a
// Drop impl. The Drop logic observes the mutation which was performed.
@ -54,7 +53,7 @@ impl<'a, 'tcx> ConstMutationChecker<'a, 'tcx> {
//
// #[const_mutation_allowed]
// pub const LOG: Log = Log { msg: "" };
match self.tcx.calculate_dtor(def_id, &mut any_dtor) {
match self.tcx.calculate_dtor(def_id, &mut |_, _| Ok(())) {
Some(_) => None,
None => Some(def_id),
}

View file

@ -1384,17 +1384,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
trait_ref: &ty::PolyTraitRef<'tcx>,
) {
let get_trait_impl = |trait_def_id| {
let mut trait_impl = None;
self.tcx.for_each_relevant_impl(
self.tcx.find_map_relevant_impl(
trait_def_id,
trait_ref.skip_binder().self_ty(),
|impl_def_id| {
if trait_impl.is_none() {
trait_impl = Some(impl_def_id);
}
},
);
trait_impl
|impl_def_id| Some(impl_def_id),
)
};
let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
let all_traits = self.tcx.all_traits(LOCAL_CRATE);