]>
Commit | Line | Data |
---|---|---|
487cf647 | 1 | use rustc_hir::def_id::DefId; |
9c376795 | 2 | use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime}; |
353b0b11 | 3 | use rustc_infer::traits::util::elaborate; |
487cf647 | 4 | use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation}; |
9c376795 FG |
5 | use rustc_middle::ty; |
6 | use rustc_span::{Span, DUMMY_SP}; | |
487cf647 FG |
7 | |
8 | use crate::traits::ObligationCtxt; | |
9 | ||
9c376795 FG |
10 | pub enum Ambiguity { |
11 | DefId(DefId), | |
12 | ParamEnv(Span), | |
13 | } | |
14 | ||
487cf647 FG |
15 | pub fn recompute_applicable_impls<'tcx>( |
16 | infcx: &InferCtxt<'tcx>, | |
17 | obligation: &TraitObligation<'tcx>, | |
9c376795 | 18 | ) -> Vec<Ambiguity> { |
487cf647 FG |
19 | let tcx = infcx.tcx; |
20 | let param_env = obligation.param_env; | |
9c376795 | 21 | |
487cf647 FG |
22 | let impl_may_apply = |impl_def_id| { |
23 | let ocx = ObligationCtxt::new_in_snapshot(infcx); | |
24 | let placeholder_obligation = | |
9ffffee4 | 25 | infcx.instantiate_binder_with_placeholders(obligation.predicate); |
487cf647 | 26 | let obligation_trait_ref = |
9c376795 | 27 | ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref); |
487cf647 FG |
28 | |
29 | let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id); | |
9c376795 | 30 | let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs); |
487cf647 FG |
31 | let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref); |
32 | ||
9c376795 FG |
33 | if let Err(_) = |
34 | ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref) | |
35 | { | |
487cf647 FG |
36 | return false; |
37 | } | |
38 | ||
39 | let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs); | |
9c376795 FG |
40 | ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| { |
41 | Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate) | |
42 | })); | |
43 | ||
44 | ocx.select_where_possible().is_empty() | |
45 | }; | |
46 | ||
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 = | |
9ffffee4 | 50 | infcx.instantiate_binder_with_placeholders(obligation.predicate); |
9c376795 FG |
51 | let obligation_trait_ref = |
52 | ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref); | |
53 | ||
9ffffee4 | 54 | let param_env_predicate = infcx.instantiate_binder_with_fresh_vars( |
9c376795 FG |
55 | DUMMY_SP, |
56 | LateBoundRegionConversionTime::HigherRankedType, | |
57 | poly_trait_predicate, | |
487cf647 | 58 | ); |
9c376795 FG |
59 | let param_env_trait_ref = |
60 | ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref); | |
61 | ||
62 | if let Err(_) = | |
63 | ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, param_env_trait_ref) | |
64 | { | |
65 | return false; | |
66 | } | |
487cf647 FG |
67 | |
68 | ocx.select_where_possible().is_empty() | |
69 | }; | |
70 | ||
9c376795 FG |
71 | let mut ambiguities = Vec::new(); |
72 | ||
487cf647 FG |
73 | tcx.for_each_relevant_impl( |
74 | obligation.predicate.def_id(), | |
75 | obligation.predicate.skip_binder().trait_ref.self_ty(), | |
76 | |impl_def_id| { | |
9c376795 FG |
77 | if infcx.probe(|_| impl_may_apply(impl_def_id)) { |
78 | ambiguities.push(Ambiguity::DefId(impl_def_id)) | |
487cf647 FG |
79 | } |
80 | }, | |
81 | ); | |
9c376795 FG |
82 | |
83 | let predicates = | |
9ffffee4 | 84 | tcx.predicates_of(obligation.cause.body_id.to_def_id()).instantiate_identity(tcx); |
353b0b11 FG |
85 | for (pred, span) in elaborate(tcx, predicates.into_iter()) { |
86 | let kind = pred.kind(); | |
9c376795 FG |
87 | if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = kind.skip_binder() |
88 | && param_env_candidate_may_apply(kind.rebind(trait_pred)) | |
89 | { | |
49aad941 | 90 | if kind.rebind(trait_pred.trait_ref) == ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_pred.def_id())) { |
9c376795 FG |
91 | ambiguities.push(Ambiguity::ParamEnv(tcx.def_span(trait_pred.def_id()))) |
92 | } else { | |
353b0b11 | 93 | ambiguities.push(Ambiguity::ParamEnv(span)) |
9c376795 FG |
94 | } |
95 | } | |
96 | } | |
97 | ||
98 | ambiguities | |
487cf647 | 99 | } |