1 use crate::rustc_trait_selection
::traits
::query
::evaluate_obligation
::InferCtxtExt
;
3 use rustc_infer
::infer
::{InferOk, TyCtxtInferExt}
;
4 use rustc_infer
::traits
;
5 use rustc_middle
::ty
::subst
::Subst
;
6 use rustc_middle
::ty
::ToPredicate
;
7 use rustc_span
::DUMMY_SP
;
11 crate struct BlanketImplFinder
<'a
, 'tcx
> {
12 crate cx
: &'a
mut core
::DocContext
<'tcx
>,
15 impl<'a
, 'tcx
> BlanketImplFinder
<'a
, 'tcx
> {
16 crate fn get_blanket_impls(&mut self, item_def_id
: DefId
) -> Vec
<Item
> {
17 let param_env
= self.cx
.tcx
.param_env(item_def_id
);
18 let ty
= self.cx
.tcx
.type_of(item_def_id
);
20 trace
!("get_blanket_impls({:?})", ty
);
21 let mut impls
= Vec
::new();
22 self.cx
.with_all_traits(|cx
, all_traits
| {
23 for &trait_def_id
in all_traits
{
24 if !cx
.cache
.access_levels
.is_public(trait_def_id
)
25 || cx
.generated_synthetics
.get(&(ty
, trait_def_id
)).is_some()
29 // NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls
30 let trait_impls
= cx
.tcx
.trait_impls_of(trait_def_id
);
31 for &impl_def_id
in trait_impls
.blanket_impls() {
33 "get_blanket_impls: Considering impl for trait '{:?}' {:?}",
37 let trait_ref
= cx
.tcx
.impl_trait_ref(impl_def_id
).unwrap();
38 let is_param
= matches
!(trait_ref
.self_ty().kind(), ty
::Param(_
));
39 let may_apply
= is_param
&& cx
.tcx
.infer_ctxt().enter(|infcx
| {
40 let substs
= infcx
.fresh_substs_for_item(DUMMY_SP
, item_def_id
);
41 let ty
= ty
.subst(infcx
.tcx
, substs
);
42 let param_env
= param_env
.subst(infcx
.tcx
, substs
);
44 let impl_substs
= infcx
.fresh_substs_for_item(DUMMY_SP
, impl_def_id
);
45 let trait_ref
= trait_ref
.subst(infcx
.tcx
, impl_substs
);
47 // Require the type the impl is implemented on to match
48 // our type, and ignore the impl if there was a mismatch.
49 let cause
= traits
::ObligationCause
::dummy();
50 let eq_result
= infcx
.at(&cause
, param_env
).eq(trait_ref
.self_ty(), ty
);
51 if let Ok(InferOk { value: (), obligations }
) = eq_result
{
52 // FIXME(eddyb) ignoring `obligations` might cause false positives.
56 "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}",
63 .predicates_of(impl_def_id
)
64 .instantiate(cx
.tcx
, impl_substs
)
68 ty
::Binder
::dummy(trait_ref
)
69 .to_poly_trait_predicate()
70 .map_bound(ty
::PredicateKind
::Trait
)
71 .to_predicate(infcx
.tcx
),
73 for predicate
in predicates
{
74 debug
!("testing predicate {:?}", predicate
);
75 let obligation
= traits
::Obligation
::new(
76 traits
::ObligationCause
::dummy(),
80 match infcx
.evaluate_obligation(&obligation
) {
81 Ok(eval_result
) if eval_result
.may_apply() => {}
82 Err(traits
::OverflowError
::Canonical
) => {}
83 Err(traits
::OverflowError
::ErrorReporting
) => {}
95 "get_blanket_impls: found applicable impl: {} for trait_ref={:?}, ty={:?}",
96 may_apply
, trait_ref
, ty
102 cx
.generated_synthetics
.insert((ty
, trait_def_id
));
106 attrs
: Default
::default(),
107 visibility
: Inherited
,
108 def_id
: ItemId
::Blanket { impl_id: impl_def_id, for_: item_def_id }
,
109 kind
: box ImplItem(Impl
{
110 unsafety
: hir
::Unsafety
::Normal
,
111 generics
: clean_ty_generics(
113 cx
.tcx
.generics_of(impl_def_id
),
114 cx
.tcx
.explicit_predicates_of(impl_def_id
),
116 // FIXME(eddyb) compute both `trait_` and `for_` from
117 // the post-inference `trait_ref`, as it's more accurate.
118 trait_
: Some(trait_ref
.clean(cx
)),
121 .associated_items(impl_def_id
)
122 .in_definition_order()
123 .map(|x
| x
.clean(cx
))
124 .collect
::<Vec
<_
>>(),
125 polarity
: ty
::ImplPolarity
::Positive
,
126 kind
: ImplKind
::Blanket(box trait_ref
.self_ty().clean(cx
)),