]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
Auto merge of #105579 - matthiaskrgr:rollup-vw5dlqc, r=matthiaskrgr
[rust.git] / compiler / rustc_trait_selection / src / traits / error_reporting / ambiguity.rs
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;
5
6 use crate::traits::ObligationCtxt;
7
8 pub fn recompute_applicable_impls<'tcx>(
9     infcx: &InferCtxt<'tcx>,
10     obligation: &TraitObligation<'tcx>,
11 ) -> Vec<DefId> {
12     let tcx = infcx.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);
21
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);
25
26         if let Err(_) = ocx.eq(&dummy_cause, param_env, obligation_trait_ref, impl_trait_ref) {
27             return false;
28         }
29
30         let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs);
31         ocx.register_obligations(
32             impl_predicates
33                 .predicates
34                 .iter()
35                 .map(|&predicate| Obligation::new(tcx, dummy_cause.clone(), param_env, predicate)),
36         );
37
38         ocx.select_where_possible().is_empty()
39     };
40
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(),
45         |impl_def_id| {
46             if infcx.probe(move |_snapshot| impl_may_apply(impl_def_id)) {
47                 impls.push(impl_def_id)
48             }
49         },
50     );
51     impls
52 }