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
.instantiate_binder_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
.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
.instantiate_binder_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
.instantiate_binder_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
.to_def_id()).instantiate_identity(tcx
);
85 for obligation
in elaborate_predicates_with_span(tcx
, predicates
.into_iter()) {
86 let kind
= obligation
.predicate
.kind();
87 if let ty
::PredicateKind
::Clause(ty
::Clause
::Trait(trait_pred
)) = kind
.skip_binder()
88 && param_env_candidate_may_apply(kind
.rebind(trait_pred
))
90 if kind
.rebind(trait_pred
.trait_ref
) == ty
::TraitRef
::identity(tcx
, trait_pred
.def_id()) {
91 ambiguities
.push(Ambiguity
::ParamEnv(tcx
.def_span(trait_pred
.def_id())))
93 ambiguities
.push(Ambiguity
::ParamEnv(obligation
.cause
.span
))