]>
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 | 12 | crate struct BlanketImplFinder<'a, 'tcx> { |
6a06907d | 13 | crate cx: &'a mut core::DocContext<'tcx>, |
b7449926 XL |
14 | } |
15 | ||
532ac7d7 | 16 | impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { |
6a06907d XL |
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); | |
48663c56 XL |
20 | |
21 | debug!("get_blanket_impls({:?})", ty); | |
b7449926 | 22 | let mut impls = Vec::new(); |
416331ca | 23 | for &trait_def_id in self.cx.tcx.all_traits(LOCAL_CRATE).iter() { |
6a06907d XL |
24 | if !self.cx.cache.access_levels.is_public(trait_def_id) |
25 | || self.cx.generated_synthetics.get(&(ty, trait_def_id)).is_some() | |
dfeec247 XL |
26 | { |
27 | continue; | |
b7449926 XL |
28 | } |
29 | self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| { | |
dfeec247 XL |
30 | debug!( |
31 | "get_blanket_impls: Considering impl for trait '{:?}' {:?}", | |
32 | trait_def_id, impl_def_id | |
33 | ); | |
48663c56 XL |
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| { | |
1b1a35ee | 36 | match trait_ref.self_ty().kind() { |
dfeec247 | 37 | ty::Param(_) => {} |
48663c56 | 38 | _ => return false, |
b7449926 XL |
39 | } |
40 | ||
6a06907d | 41 | let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id); |
b7449926 XL |
42 | let ty = ty.subst(infcx.tcx, substs); |
43 | let param_env = param_env.subst(infcx.tcx, substs); | |
44 | ||
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); | |
47 | ||
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(); | |
dfeec247 | 51 | let eq_result = infcx.at(&cause, param_env).eq(trait_ref.self_ty(), ty); |
b7449926 XL |
52 | if let Ok(InferOk { value: (), obligations }) = eq_result { |
53 | // FIXME(eddyb) ignoring `obligations` might cause false positives. | |
54 | drop(obligations); | |
55 | ||
0bf4aa26 | 56 | debug!( |
13cf67c4 | 57 | "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}", |
dfeec247 | 58 | param_env, trait_ref, ty |
0bf4aa26 | 59 | ); |
fc512014 XL |
60 | let predicates = self |
61 | .cx | |
62 | .tcx | |
63 | .predicates_of(impl_def_id) | |
64 | .instantiate(self.cx.tcx, impl_substs) | |
65 | .predicates | |
66 | .into_iter() | |
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(), | |
72 | param_env, | |
73 | predicate, | |
74 | ); | |
75 | match infcx.evaluate_obligation(&obligation) { | |
76 | Ok(eval_result) if eval_result.may_apply() => {} | |
77 | Err(traits::OverflowError) => {} | |
78 | _ => { | |
79 | return false; | |
80 | } | |
81 | } | |
b7449926 | 82 | } |
fc512014 | 83 | true |
48663c56 XL |
84 | } else { |
85 | false | |
b7449926 XL |
86 | } |
87 | }); | |
dfeec247 | 88 | debug!( |
1b1a35ee | 89 | "get_blanket_impls: found applicable impl: {} for trait_ref={:?}, ty={:?}", |
dfeec247 XL |
90 | may_apply, trait_ref, ty |
91 | ); | |
48663c56 XL |
92 | if !may_apply { |
93 | return; | |
94 | } | |
95 | ||
6a06907d | 96 | self.cx.generated_synthetics.insert((ty, trait_def_id)); |
dfeec247 XL |
97 | let provided_trait_methods = self |
98 | .cx | |
99 | .tcx | |
100 | .provided_trait_methods(trait_def_id) | |
fc512014 | 101 | .map(|meth| meth.ident.name) |
dfeec247 | 102 | .collect(); |
48663c56 XL |
103 | |
104 | impls.push(Item { | |
105 | source: self.cx.tcx.def_span(impl_def_id).clean(self.cx), | |
106 | name: None, | |
107 | attrs: Default::default(), | |
e74abb32 | 108 | visibility: Inherited, |
48663c56 | 109 | def_id: self.cx.next_def_id(impl_def_id.krate), |
5869c6ff | 110 | kind: box ImplItem(Impl { |
48663c56 XL |
111 | unsafety: hir::Unsafety::Normal, |
112 | generics: ( | |
113 | self.cx.tcx.generics_of(impl_def_id), | |
e74abb32 | 114 | self.cx.tcx.explicit_predicates_of(impl_def_id), |
dfeec247 XL |
115 | ) |
116 | .clean(self.cx), | |
48663c56 XL |
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), | |
dfeec247 XL |
122 | items: self |
123 | .cx | |
124 | .tcx | |
125 | .associated_items(impl_def_id) | |
74b04a01 | 126 | .in_definition_order() |
dfeec247 XL |
127 | .collect::<Vec<_>>() |
128 | .clean(self.cx), | |
5869c6ff | 129 | negative_polarity: false, |
48663c56 XL |
130 | synthetic: false, |
131 | blanket_impl: Some(trait_ref.self_ty().clean(self.cx)), | |
132 | }), | |
133 | }); | |
b7449926 XL |
134 | }); |
135 | } | |
136 | impls | |
137 | } | |
138 | } |