]>
Commit | Line | Data |
---|---|---|
ba9703b0 | 1 | use crate::rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; |
dfeec247 XL |
2 | use rustc_hir as hir; |
3 | use rustc_hir::def_id::LOCAL_CRATE; | |
74b04a01 XL |
4 | use rustc_infer::infer::{InferOk, TyCtxtInferExt}; |
5 | use rustc_infer::traits; | |
ba9703b0 XL |
6 | use rustc_middle::ty::subst::Subst; |
7 | use rustc_middle::ty::{ToPredicate, WithConstness}; | |
dfeec247 | 8 | use rustc_span::DUMMY_SP; |
b7449926 | 9 | |
b7449926 XL |
10 | use super::*; |
11 | ||
fc512014 XL |
12 | crate struct BlanketImplFinder<'a, 'tcx> { |
13 | crate cx: &'a core::DocContext<'tcx>, | |
b7449926 XL |
14 | } |
15 | ||
532ac7d7 | 16 | impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { |
fc512014 | 17 | crate fn new(cx: &'a core::DocContext<'tcx>) -> Self { |
b7449926 XL |
18 | BlanketImplFinder { cx } |
19 | } | |
20 | ||
48663c56 XL |
21 | // FIXME(eddyb) figure out a better way to pass information about |
22 | // parametrization of `ty` than `param_env_def_id`. | |
fc512014 | 23 | crate fn get_blanket_impls(&self, ty: Ty<'tcx>, param_env_def_id: DefId) -> Vec<Item> { |
48663c56 XL |
24 | let param_env = self.cx.tcx.param_env(param_env_def_id); |
25 | ||
26 | debug!("get_blanket_impls({:?})", ty); | |
b7449926 | 27 | let mut impls = Vec::new(); |
416331ca | 28 | for &trait_def_id in self.cx.tcx.all_traits(LOCAL_CRATE).iter() { |
dfeec247 XL |
29 | if !self.cx.renderinfo.borrow().access_levels.is_public(trait_def_id) |
30 | || self.cx.generated_synthetics.borrow_mut().get(&(ty, trait_def_id)).is_some() | |
31 | { | |
32 | continue; | |
b7449926 XL |
33 | } |
34 | self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| { | |
dfeec247 XL |
35 | debug!( |
36 | "get_blanket_impls: Considering impl for trait '{:?}' {:?}", | |
37 | trait_def_id, impl_def_id | |
38 | ); | |
48663c56 XL |
39 | let trait_ref = self.cx.tcx.impl_trait_ref(impl_def_id).unwrap(); |
40 | let may_apply = self.cx.tcx.infer_ctxt().enter(|infcx| { | |
1b1a35ee | 41 | match trait_ref.self_ty().kind() { |
dfeec247 | 42 | ty::Param(_) => {} |
48663c56 | 43 | _ => return false, |
b7449926 XL |
44 | } |
45 | ||
48663c56 | 46 | let substs = infcx.fresh_substs_for_item(DUMMY_SP, param_env_def_id); |
b7449926 XL |
47 | let ty = ty.subst(infcx.tcx, substs); |
48 | let param_env = param_env.subst(infcx.tcx, substs); | |
49 | ||
50 | let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id); | |
51 | let trait_ref = trait_ref.subst(infcx.tcx, impl_substs); | |
52 | ||
53 | // Require the type the impl is implemented on to match | |
54 | // our type, and ignore the impl if there was a mismatch. | |
55 | let cause = traits::ObligationCause::dummy(); | |
dfeec247 | 56 | let eq_result = infcx.at(&cause, param_env).eq(trait_ref.self_ty(), ty); |
b7449926 XL |
57 | if let Ok(InferOk { value: (), obligations }) = eq_result { |
58 | // FIXME(eddyb) ignoring `obligations` might cause false positives. | |
59 | drop(obligations); | |
60 | ||
0bf4aa26 | 61 | debug!( |
13cf67c4 | 62 | "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}", |
dfeec247 | 63 | param_env, trait_ref, ty |
0bf4aa26 | 64 | ); |
fc512014 XL |
65 | let predicates = self |
66 | .cx | |
67 | .tcx | |
68 | .predicates_of(impl_def_id) | |
69 | .instantiate(self.cx.tcx, impl_substs) | |
70 | .predicates | |
71 | .into_iter() | |
72 | .chain(Some(trait_ref.without_const().to_predicate(infcx.tcx))); | |
73 | for predicate in predicates { | |
74 | debug!("testing predicate {:?}", predicate); | |
75 | let obligation = traits::Obligation::new( | |
76 | traits::ObligationCause::dummy(), | |
77 | param_env, | |
78 | predicate, | |
79 | ); | |
80 | match infcx.evaluate_obligation(&obligation) { | |
81 | Ok(eval_result) if eval_result.may_apply() => {} | |
82 | Err(traits::OverflowError) => {} | |
83 | _ => { | |
84 | return false; | |
85 | } | |
86 | } | |
b7449926 | 87 | } |
fc512014 | 88 | true |
48663c56 XL |
89 | } else { |
90 | false | |
b7449926 XL |
91 | } |
92 | }); | |
dfeec247 | 93 | debug!( |
1b1a35ee | 94 | "get_blanket_impls: found applicable impl: {} for trait_ref={:?}, ty={:?}", |
dfeec247 XL |
95 | may_apply, trait_ref, ty |
96 | ); | |
48663c56 XL |
97 | if !may_apply { |
98 | return; | |
99 | } | |
100 | ||
dfeec247 XL |
101 | self.cx.generated_synthetics.borrow_mut().insert((ty, trait_def_id)); |
102 | let provided_trait_methods = self | |
103 | .cx | |
104 | .tcx | |
105 | .provided_trait_methods(trait_def_id) | |
fc512014 | 106 | .map(|meth| meth.ident.name) |
dfeec247 | 107 | .collect(); |
48663c56 XL |
108 | |
109 | impls.push(Item { | |
110 | source: self.cx.tcx.def_span(impl_def_id).clean(self.cx), | |
111 | name: None, | |
112 | attrs: Default::default(), | |
e74abb32 | 113 | visibility: Inherited, |
48663c56 | 114 | def_id: self.cx.next_def_id(impl_def_id.krate), |
fc512014 | 115 | kind: ImplItem(Impl { |
48663c56 XL |
116 | unsafety: hir::Unsafety::Normal, |
117 | generics: ( | |
118 | self.cx.tcx.generics_of(impl_def_id), | |
e74abb32 | 119 | self.cx.tcx.explicit_predicates_of(impl_def_id), |
dfeec247 XL |
120 | ) |
121 | .clean(self.cx), | |
48663c56 XL |
122 | provided_trait_methods, |
123 | // FIXME(eddyb) compute both `trait_` and `for_` from | |
124 | // the post-inference `trait_ref`, as it's more accurate. | |
125 | trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap()), | |
126 | for_: ty.clean(self.cx), | |
dfeec247 XL |
127 | items: self |
128 | .cx | |
129 | .tcx | |
130 | .associated_items(impl_def_id) | |
74b04a01 | 131 | .in_definition_order() |
dfeec247 XL |
132 | .collect::<Vec<_>>() |
133 | .clean(self.cx), | |
48663c56 XL |
134 | polarity: None, |
135 | synthetic: false, | |
136 | blanket_impl: Some(trait_ref.self_ty().clean(self.cx)), | |
137 | }), | |
138 | }); | |
b7449926 XL |
139 | }); |
140 | } | |
141 | impls | |
142 | } | |
143 | } |