1 use rustc_hir::def_id::DefId;
2 use rustc_infer::infer::InferCtxt;
3 use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation};
4 use rustc_span::DUMMY_SP;
6 use crate::traits::ObligationCtxt;
8 pub fn recompute_applicable_impls<'tcx>(
9 infcx: &InferCtxt<'tcx>,
10 obligation: &TraitObligation<'tcx>,
13 let param_env = obligation.param_env;
14 let dummy_cause = ObligationCause::dummy();
15 let impl_may_apply = |impl_def_id| {
16 let ocx = ObligationCtxt::new_in_snapshot(infcx);
17 let placeholder_obligation =
18 infcx.replace_bound_vars_with_placeholders(obligation.predicate);
19 let obligation_trait_ref =
20 ocx.normalize(&dummy_cause, param_env, placeholder_obligation.trait_ref);
22 let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
23 let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs);
24 let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
26 if let Err(_) = ocx.eq(&dummy_cause, param_env, obligation_trait_ref, impl_trait_ref) {
30 let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs);
31 ocx.register_obligations(
35 .map(|&predicate| Obligation::new(tcx, dummy_cause.clone(), param_env, predicate)),
38 ocx.select_where_possible().is_empty()
41 let mut impls = Vec::new();
42 tcx.for_each_relevant_impl(
43 obligation.predicate.def_id(),
44 obligation.predicate.skip_binder().trait_ref.self_ty(),
46 if infcx.probe(move |_snapshot| impl_may_apply(impl_def_id)) {
47 impls.push(impl_def_id)