Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TraitDef::find_map_relevant_impl #77754

Merged
merged 3 commits into from
Oct 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions compiler/rustc_middle/src/ty/trait_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically I'm changing the semantics here. The old code returned the last def_id, while the new one returns the first. Let me know if this is a problem.

}
}
None
});

Some(ty::Destructor { did: dtor_did? })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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),
}
Expand Down
12 changes: 3 additions & 9 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
16 changes: 6 additions & 10 deletions src/librustdoc/passes/collect_intra_doc_links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -650,14 +650,9 @@ fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> Fx
let ty = cx.tcx.type_of(type_);
let iter = in_scope_traits.iter().flat_map(|&trait_| {
trace!("considering explicit impl for trait {:?}", trait_);
let mut saw_impl = false;
// Look at each trait implementation to see if it's an impl for `did`
cx.tcx.for_each_relevant_impl(trait_, ty, |impl_| {
// FIXME: this is inefficient, find a way to short-circuit for_each_* so this doesn't take as long
if saw_impl {
return;
}

// Look at each trait implementation to see if it's an impl for `did`
cx.tcx.find_map_relevant_impl(trait_, ty, |impl_| {
let trait_ref = cx.tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
// Check if these are the same type.
let impl_type = trait_ref.self_ty();
Expand All @@ -668,7 +663,7 @@ fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> Fx
type_
);
// Fast path: if this is a primitive simple `==` will work
saw_impl = impl_type == ty
let saw_impl = impl_type == ty
|| match impl_type.kind() {
// Check if these are the same def_id
ty::Adt(def, _) => {
Expand All @@ -678,8 +673,9 @@ fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> Fx
ty::Foreign(def_id) => *def_id == type_,
_ => false,
};
});
if saw_impl { Some(trait_) } else { None }

if saw_impl { Some(trait_) } else { None }
})
});
iter.collect()
}
Expand Down