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