1 use crate::rustc_trait_selection
::traits
::query
::evaluate_obligation
::InferCtxtExt
;
3 use rustc_hir
::def_id
::LOCAL_CRATE
;
4 use rustc_infer
::infer
::{InferOk, TyCtxtInferExt}
;
5 use rustc_infer
::traits
;
6 use rustc_middle
::ty
::subst
::Subst
;
7 use rustc_middle
::ty
::{ToPredicate, WithConstness}
;
8 use rustc_span
::DUMMY_SP
;
12 crate struct BlanketImplFinder
<'a
, 'tcx
> {
13 crate cx
: &'a
mut core
::DocContext
<'tcx
>,
16 impl<'a
, 'tcx
> BlanketImplFinder
<'a
, 'tcx
> {
17 crate fn get_blanket_impls(&mut self, item_def_id
: DefId
) -> Vec
<Item
> {
18 let param_env
= self.cx
.tcx
.param_env(item_def_id
);
19 let ty
= self.cx
.tcx
.type_of(item_def_id
);
21 debug
!("get_blanket_impls({:?})", ty
);
22 let mut impls
= Vec
::new();
23 for &trait_def_id
in self.cx
.tcx
.all_traits(LOCAL_CRATE
).iter() {
24 if !self.cx
.cache
.access_levels
.is_public(trait_def_id
)
25 || self.cx
.generated_synthetics
.get(&(ty
, trait_def_id
)).is_some()
29 self.cx
.tcx
.for_each_relevant_impl(trait_def_id
, ty
, |impl_def_id
| {
31 "get_blanket_impls: Considering impl for trait '{:?}' {:?}",
32 trait_def_id
, impl_def_id
34 let trait_ref
= self.cx
.tcx
.impl_trait_ref(impl_def_id
).unwrap();
35 let may_apply
= self.cx
.tcx
.infer_ctxt().enter(|infcx
| {
36 match trait_ref
.self_ty().kind() {
41 let substs
= infcx
.fresh_substs_for_item(DUMMY_SP
, item_def_id
);
42 let ty
= ty
.subst(infcx
.tcx
, substs
);
43 let param_env
= param_env
.subst(infcx
.tcx
, substs
);
45 let impl_substs
= infcx
.fresh_substs_for_item(DUMMY_SP
, impl_def_id
);
46 let trait_ref
= trait_ref
.subst(infcx
.tcx
, impl_substs
);
48 // Require the type the impl is implemented on to match
49 // our type, and ignore the impl if there was a mismatch.
50 let cause
= traits
::ObligationCause
::dummy();
51 let eq_result
= infcx
.at(&cause
, param_env
).eq(trait_ref
.self_ty(), ty
);
52 if let Ok(InferOk { value: (), obligations }
) = eq_result
{
53 // FIXME(eddyb) ignoring `obligations` might cause false positives.
57 "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}",
58 param_env
, trait_ref
, ty
63 .predicates_of(impl_def_id
)
64 .instantiate(self.cx
.tcx
, impl_substs
)
67 .chain(Some(trait_ref
.without_const().to_predicate(infcx
.tcx
)));
68 for predicate
in predicates
{
69 debug
!("testing predicate {:?}", predicate
);
70 let obligation
= traits
::Obligation
::new(
71 traits
::ObligationCause
::dummy(),
75 match infcx
.evaluate_obligation(&obligation
) {
76 Ok(eval_result
) if eval_result
.may_apply() => {}
77 Err(traits
::OverflowError
) => {}
89 "get_blanket_impls: found applicable impl: {} for trait_ref={:?}, ty={:?}",
90 may_apply
, trait_ref
, ty
96 self.cx
.generated_synthetics
.insert((ty
, trait_def_id
));
97 let provided_trait_methods
= self
100 .provided_trait_methods(trait_def_id
)
101 .map(|meth
| meth
.ident
.name
)
105 source
: self.cx
.tcx
.def_span(impl_def_id
).clean(self.cx
),
107 attrs
: Default
::default(),
108 visibility
: Inherited
,
109 def_id
: self.cx
.next_def_id(impl_def_id
.krate
),
110 kind
: box ImplItem(Impl
{
111 unsafety
: hir
::Unsafety
::Normal
,
113 self.cx
.tcx
.generics_of(impl_def_id
),
114 self.cx
.tcx
.explicit_predicates_of(impl_def_id
),
117 provided_trait_methods
,
118 // FIXME(eddyb) compute both `trait_` and `for_` from
119 // the post-inference `trait_ref`, as it's more accurate.
120 trait_
: Some(trait_ref
.clean(self.cx
).get_trait_type().unwrap()),
121 for_
: ty
.clean(self.cx
),
125 .associated_items(impl_def_id
)
126 .in_definition_order()
129 negative_polarity
: false,
131 blanket_impl
: Some(trait_ref
.self_ty().clean(self.cx
)),