3 use rustc
::ty
::ToPredicate
;
4 use rustc
::ty
::subst
::Subst
;
5 use rustc
::infer
::InferOk
;
6 use rustc
::hir
::def_id
::LOCAL_CRATE
;
7 use syntax_pos
::DUMMY_SP
;
11 pub struct BlanketImplFinder
<'a
, 'tcx
> {
12 pub cx
: &'a core
::DocContext
<'tcx
>,
15 impl<'a
, 'tcx
> BlanketImplFinder
<'a
, 'tcx
> {
16 pub fn new(cx
: &'a core
::DocContext
<'tcx
>) -> Self {
17 BlanketImplFinder { cx }
20 // FIXME(eddyb) figure out a better way to pass information about
21 // parametrization of `ty` than `param_env_def_id`.
22 pub fn get_blanket_impls(
25 param_env_def_id
: DefId
,
27 let param_env
= self.cx
.tcx
.param_env(param_env_def_id
);
29 debug
!("get_blanket_impls({:?})", ty
);
30 let mut impls
= Vec
::new();
31 for &trait_def_id
in self.cx
.tcx
.all_traits(LOCAL_CRATE
).iter() {
32 if !self.cx
.renderinfo
.borrow().access_levels
.is_public(trait_def_id
) ||
33 self.cx
.generated_synthetics
35 .get(&(ty
, trait_def_id
))
39 self.cx
.tcx
.for_each_relevant_impl(trait_def_id
, ty
, |impl_def_id
| {
40 debug
!("get_blanket_impls: Considering impl for trait '{:?}' {:?}",
41 trait_def_id
, impl_def_id
);
42 let trait_ref
= self.cx
.tcx
.impl_trait_ref(impl_def_id
).unwrap();
43 let may_apply
= self.cx
.tcx
.infer_ctxt().enter(|infcx
| {
44 match trait_ref
.self_ty().kind
{
49 let substs
= infcx
.fresh_substs_for_item(DUMMY_SP
, param_env_def_id
);
50 let ty
= ty
.subst(infcx
.tcx
, substs
);
51 let param_env
= param_env
.subst(infcx
.tcx
, substs
);
53 let impl_substs
= infcx
.fresh_substs_for_item(DUMMY_SP
, impl_def_id
);
54 let trait_ref
= trait_ref
.subst(infcx
.tcx
, impl_substs
);
56 // Require the type the impl is implemented on to match
57 // our type, and ignore the impl if there was a mismatch.
58 let cause
= traits
::ObligationCause
::dummy();
59 let eq_result
= infcx
.at(&cause
, param_env
)
60 .eq(trait_ref
.self_ty(), ty
);
61 if let Ok(InferOk { value: (), obligations }
) = eq_result
{
62 // FIXME(eddyb) ignoring `obligations` might cause false positives.
66 "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}",
67 param_env
, trait_ref
, ty
69 match infcx
.evaluate_obligation(
70 &traits
::Obligation
::new(
73 trait_ref
.to_predicate(),
76 Ok(eval_result
) => eval_result
.may_apply(),
77 Err(traits
::OverflowError
) => true, // overflow doesn't mean yes *or* no
83 debug
!("get_blanket_impls: found applicable impl: {}\
84 for trait_ref={:?}, ty={:?}",
85 may_apply
, trait_ref
, ty
);
90 self.cx
.generated_synthetics
.borrow_mut()
91 .insert((ty
, trait_def_id
));
92 let provided_trait_methods
=
93 self.cx
.tcx
.provided_trait_methods(trait_def_id
)
95 .map(|meth
| meth
.ident
.to_string())
99 source
: self.cx
.tcx
.def_span(impl_def_id
).clean(self.cx
),
101 attrs
: Default
::default(),
102 visibility
: Inherited
,
103 def_id
: self.cx
.next_def_id(impl_def_id
.krate
),
106 inner
: ImplItem(Impl
{
107 unsafety
: hir
::Unsafety
::Normal
,
109 self.cx
.tcx
.generics_of(impl_def_id
),
110 self.cx
.tcx
.explicit_predicates_of(impl_def_id
),
112 provided_trait_methods
,
113 // FIXME(eddyb) compute both `trait_` and `for_` from
114 // the post-inference `trait_ref`, as it's more accurate.
115 trait_
: Some(trait_ref
.clean(self.cx
).get_trait_type().unwrap()),
116 for_
: ty
.clean(self.cx
),
117 items
: self.cx
.tcx
.associated_items(impl_def_id
)
122 blanket_impl
: Some(trait_ref
.self_ty().clean(self.cx
)),