1 use rustc_hir::def_id::DefId;
2 use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime};
3 use rustc_infer::traits::util::elaborate_predicates_with_span;
4 use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation};
6 use rustc_span::{Span, DUMMY_SP};
8 use crate::traits::ObligationCtxt;
15 pub fn recompute_applicable_impls<'tcx>(
16 infcx: &InferCtxt<'tcx>,
17 obligation: &TraitObligation<'tcx>,
20 let param_env = obligation.param_env;
22 let impl_may_apply = |impl_def_id| {
23 let ocx = ObligationCtxt::new_in_snapshot(infcx);
24 let placeholder_obligation =
25 infcx.replace_bound_vars_with_placeholders(obligation.predicate);
26 let obligation_trait_ref =
27 ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
29 let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
30 let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs);
31 let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
34 ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref)
39 let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs);
40 ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| {
41 Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
44 ocx.select_where_possible().is_empty()
47 let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| {
48 let ocx = ObligationCtxt::new_in_snapshot(infcx);
49 let placeholder_obligation =
50 infcx.replace_bound_vars_with_placeholders(obligation.predicate);
51 let obligation_trait_ref =
52 ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
54 let param_env_predicate = infcx.replace_bound_vars_with_fresh_vars(
56 LateBoundRegionConversionTime::HigherRankedType,
59 let param_env_trait_ref =
60 ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref);
63 ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, param_env_trait_ref)
68 ocx.select_where_possible().is_empty()
71 let mut ambiguities = Vec::new();
73 tcx.for_each_relevant_impl(
74 obligation.predicate.def_id(),
75 obligation.predicate.skip_binder().trait_ref.self_ty(),
77 if infcx.probe(|_| impl_may_apply(impl_def_id)) {
78 ambiguities.push(Ambiguity::DefId(impl_def_id))
84 tcx.predicates_of(obligation.cause.body_id.owner.to_def_id()).instantiate_identity(tcx);
86 elaborate_predicates_with_span(tcx, std::iter::zip(predicates.predicates, predicates.spans))
88 let kind = obligation.predicate.kind();
89 if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = kind.skip_binder()
90 && param_env_candidate_may_apply(kind.rebind(trait_pred))
92 if kind.rebind(trait_pred.trait_ref) == ty::TraitRef::identity(tcx, trait_pred.def_id()) {
93 ambiguities.push(Ambiguity::ParamEnv(tcx.def_span(trait_pred.def_id())))
95 ambiguities.push(Ambiguity::ParamEnv(obligation.cause.span))