]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_trait_selection / src / traits / error_reporting / ambiguity.rs
CommitLineData
487cf647 1use rustc_hir::def_id::DefId;
9c376795 2use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime};
353b0b11 3use rustc_infer::traits::util::elaborate;
487cf647 4use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation};
9c376795
FG
5use rustc_middle::ty;
6use rustc_span::{Span, DUMMY_SP};
487cf647
FG
7
8use crate::traits::ObligationCtxt;
9
9c376795
FG
10pub enum Ambiguity {
11 DefId(DefId),
12 ParamEnv(Span),
13}
14
487cf647
FG
15pub 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}