]> git.lizzy.rs Git - rust.git/blob - src/librustc_infer/traits/util.rs
convert trivial predicates
[rust.git] / src / librustc_infer / traits / util.rs
1 use smallvec::smallvec;
2
3 use crate::traits::{Obligation, ObligationCause, PredicateObligation};
4 use rustc_data_structures::fx::FxHashSet;
5 use rustc_middle::ty::outlives::Component;
6 use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, TyCtxt, WithConstness};
7 use rustc_span::Span;
8
9 pub fn anonymize_predicate<'tcx>(
10     tcx: TyCtxt<'tcx>,
11     pred: ty::Predicate<'tcx>,
12 ) -> ty::Predicate<'tcx> {
13     let kind = pred.kint(tcx);
14     let new = match kind {
15         ty::PredicateKint::ForAll(binder) => {
16             ty::PredicateKint::ForAll(tcx.anonymize_late_bound_regions(binder))
17         }
18         &ty::PredicateKint::Trait(data, constness) => ty::PredicateKint::Trait(data, constness),
19
20         &ty::PredicateKint::RegionOutlives(data) => ty::PredicateKint::RegionOutlives(data),
21
22         &ty::PredicateKint::TypeOutlives(data) => ty::PredicateKint::TypeOutlives(data),
23
24         &ty::PredicateKint::Projection(data) => ty::PredicateKint::Projection(data),
25
26         &ty::PredicateKint::WellFormed(data) => ty::PredicateKint::WellFormed(data),
27
28         &ty::PredicateKint::ObjectSafe(data) => ty::PredicateKint::ObjectSafe(data),
29
30         &ty::PredicateKint::ClosureKind(closure_def_id, closure_substs, kind) => {
31             ty::PredicateKint::ClosureKind(closure_def_id, closure_substs, kind)
32         }
33
34         &ty::PredicateKint::Subtype(data) => ty::PredicateKint::Subtype(data),
35
36         &ty::PredicateKint::ConstEvaluatable(def_id, substs) => {
37             ty::PredicateKint::ConstEvaluatable(def_id, substs)
38         }
39
40         &ty::PredicateKint::ConstEquate(c1, c2) => ty::PredicateKint::ConstEquate(c1, c2),
41     };
42
43     if new != *kind { new.to_predicate(tcx) } else { pred }
44 }
45
46 struct PredicateSet<'tcx> {
47     tcx: TyCtxt<'tcx>,
48     set: FxHashSet<ty::Predicate<'tcx>>,
49 }
50
51 impl PredicateSet<'tcx> {
52     fn new(tcx: TyCtxt<'tcx>) -> Self {
53         Self { tcx, set: Default::default() }
54     }
55
56     fn insert(&mut self, pred: ty::Predicate<'tcx>) -> bool {
57         // We have to be careful here because we want
58         //
59         //    for<'a> Foo<&'a i32>
60         //
61         // and
62         //
63         //    for<'b> Foo<&'b i32>
64         //
65         // to be considered equivalent. So normalize all late-bound
66         // regions before we throw things into the underlying set.
67         self.set.insert(anonymize_predicate(self.tcx, pred))
68     }
69 }
70
71 impl Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
72     fn extend<I: IntoIterator<Item = ty::Predicate<'tcx>>>(&mut self, iter: I) {
73         for pred in iter {
74             self.insert(pred);
75         }
76     }
77
78     fn extend_one(&mut self, pred: ty::Predicate<'tcx>) {
79         self.insert(pred);
80     }
81
82     fn extend_reserve(&mut self, additional: usize) {
83         Extend::<ty::Predicate<'tcx>>::extend_reserve(&mut self.set, additional);
84     }
85 }
86
87 ///////////////////////////////////////////////////////////////////////////
88 // `Elaboration` iterator
89 ///////////////////////////////////////////////////////////////////////////
90
91 /// "Elaboration" is the process of identifying all the predicates that
92 /// are implied by a source predicate. Currently, this basically means
93 /// walking the "supertraits" and other similar assumptions. For example,
94 /// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd`
95 /// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that
96 /// `T: Foo`, then we know that `T: 'static`.
97 pub struct Elaborator<'tcx> {
98     stack: Vec<PredicateObligation<'tcx>>,
99     visited: PredicateSet<'tcx>,
100 }
101
102 pub fn elaborate_trait_ref<'tcx>(
103     tcx: TyCtxt<'tcx>,
104     trait_ref: ty::PolyTraitRef<'tcx>,
105 ) -> Elaborator<'tcx> {
106     elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx)))
107 }
108
109 pub fn elaborate_trait_refs<'tcx>(
110     tcx: TyCtxt<'tcx>,
111     trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
112 ) -> Elaborator<'tcx> {
113     let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate(tcx));
114     elaborate_predicates(tcx, predicates)
115 }
116
117 pub fn elaborate_predicates<'tcx>(
118     tcx: TyCtxt<'tcx>,
119     predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
120 ) -> Elaborator<'tcx> {
121     let obligations = predicates.map(|predicate| predicate_obligation(predicate, None)).collect();
122     elaborate_obligations(tcx, obligations)
123 }
124
125 pub fn elaborate_obligations<'tcx>(
126     tcx: TyCtxt<'tcx>,
127     mut obligations: Vec<PredicateObligation<'tcx>>,
128 ) -> Elaborator<'tcx> {
129     let mut visited = PredicateSet::new(tcx);
130     obligations.retain(|obligation| visited.insert(obligation.predicate));
131     Elaborator { stack: obligations, visited }
132 }
133
134 fn predicate_obligation<'tcx>(
135     predicate: ty::Predicate<'tcx>,
136     span: Option<Span>,
137 ) -> PredicateObligation<'tcx> {
138     let cause = if let Some(span) = span {
139         ObligationCause::dummy_with_span(span)
140     } else {
141         ObligationCause::dummy()
142     };
143
144     Obligation { cause, param_env: ty::ParamEnv::empty(), recursion_depth: 0, predicate }
145 }
146
147 impl Elaborator<'tcx> {
148     pub fn filter_to_traits(self) -> FilterToTraits<Self> {
149         FilterToTraits::new(self)
150     }
151
152     fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
153         let tcx = self.visited.tcx;
154         match obligation.predicate.kind() {
155             ty::PredicateKind::Trait(ref data, _) => {
156                 // Get predicates declared on the trait.
157                 let predicates = tcx.super_predicates_of(data.def_id());
158
159                 let obligations = predicates.predicates.iter().map(|(pred, span)| {
160                     predicate_obligation(
161                         pred.subst_supertrait(tcx, &data.to_poly_trait_ref()),
162                         Some(*span),
163                     )
164                 });
165                 debug!("super_predicates: data={:?}", data);
166
167                 // Only keep those bounds that we haven't already seen.
168                 // This is necessary to prevent infinite recursion in some
169                 // cases. One common case is when people define
170                 // `trait Sized: Sized { }` rather than `trait Sized { }`.
171                 let visited = &mut self.visited;
172                 let obligations = obligations.filter(|o| visited.insert(o.predicate));
173
174                 self.stack.extend(obligations);
175             }
176             ty::PredicateKind::WellFormed(..) => {
177                 // Currently, we do not elaborate WF predicates,
178                 // although we easily could.
179             }
180             ty::PredicateKind::ObjectSafe(..) => {
181                 // Currently, we do not elaborate object-safe
182                 // predicates.
183             }
184             ty::PredicateKind::Subtype(..) => {
185                 // Currently, we do not "elaborate" predicates like `X <: Y`,
186                 // though conceivably we might.
187             }
188             ty::PredicateKind::Projection(..) => {
189                 // Nothing to elaborate in a projection predicate.
190             }
191             ty::PredicateKind::ClosureKind(..) => {
192                 // Nothing to elaborate when waiting for a closure's kind to be inferred.
193             }
194             ty::PredicateKind::ConstEvaluatable(..) => {
195                 // Currently, we do not elaborate const-evaluatable
196                 // predicates.
197             }
198             ty::PredicateKind::ConstEquate(..) => {
199                 // Currently, we do not elaborate const-equate
200                 // predicates.
201             }
202             ty::PredicateKind::RegionOutlives(..) => {
203                 // Nothing to elaborate from `'a: 'b`.
204             }
205             ty::PredicateKind::TypeOutlives(ref data) => {
206                 // We know that `T: 'a` for some type `T`. We can
207                 // often elaborate this. For example, if we know that
208                 // `[U]: 'a`, that implies that `U: 'a`. Similarly, if
209                 // we know `&'a U: 'b`, then we know that `'a: 'b` and
210                 // `U: 'b`.
211                 //
212                 // We can basically ignore bound regions here. So for
213                 // example `for<'c> Foo<'a,'c>: 'b` can be elaborated to
214                 // `'a: 'b`.
215
216                 // Ignore `for<'a> T: 'a` -- we might in the future
217                 // consider this as evidence that `T: 'static`, but
218                 // I'm a bit wary of such constructions and so for now
219                 // I want to be conservative. --nmatsakis
220                 let ty_max = data.skip_binder().0;
221                 let r_min = data.skip_binder().1;
222                 if r_min.is_late_bound() {
223                     return;
224                 }
225
226                 let visited = &mut self.visited;
227                 let mut components = smallvec![];
228                 tcx.push_outlives_components(ty_max, &mut components);
229                 self.stack.extend(
230                     components
231                         .into_iter()
232                         .filter_map(|component| match component {
233                             Component::Region(r) => {
234                                 if r.is_late_bound() {
235                                     None
236                                 } else {
237                                     Some(ty::PredicateKint::RegionOutlives(ty::OutlivesPredicate(
238                                         r, r_min,
239                                     )))
240                                 }
241                             }
242
243                             Component::Param(p) => {
244                                 let ty = tcx.mk_ty_param(p.index, p.name);
245                                 Some(ty::PredicateKint::TypeOutlives(ty::OutlivesPredicate(
246                                     ty, r_min,
247                                 )))
248                             }
249
250                             Component::UnresolvedInferenceVariable(_) => None,
251
252                             Component::Projection(_) | Component::EscapingProjection(_) => {
253                                 // We can probably do more here. This
254                                 // corresponds to a case like `<T as
255                                 // Foo<'a>>::U: 'b`.
256                                 None
257                             }
258                         })
259                         .map(|predicate_kind| predicate_kind.to_predicate(tcx))
260                         .filter(|&predicate| visited.insert(predicate))
261                         .map(|predicate| predicate_obligation(predicate, None)),
262                 );
263             }
264         }
265     }
266 }
267
268 impl Iterator for Elaborator<'tcx> {
269     type Item = PredicateObligation<'tcx>;
270
271     fn size_hint(&self) -> (usize, Option<usize>) {
272         (self.stack.len(), None)
273     }
274
275     fn next(&mut self) -> Option<Self::Item> {
276         // Extract next item from top-most stack frame, if any.
277         if let Some(obligation) = self.stack.pop() {
278             self.elaborate(&obligation);
279             Some(obligation)
280         } else {
281             None
282         }
283     }
284 }
285
286 ///////////////////////////////////////////////////////////////////////////
287 // Supertrait iterator
288 ///////////////////////////////////////////////////////////////////////////
289
290 pub type Supertraits<'tcx> = FilterToTraits<Elaborator<'tcx>>;
291
292 pub fn supertraits<'tcx>(
293     tcx: TyCtxt<'tcx>,
294     trait_ref: ty::PolyTraitRef<'tcx>,
295 ) -> Supertraits<'tcx> {
296     elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
297 }
298
299 pub fn transitive_bounds<'tcx>(
300     tcx: TyCtxt<'tcx>,
301     bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
302 ) -> Supertraits<'tcx> {
303     elaborate_trait_refs(tcx, bounds).filter_to_traits()
304 }
305
306 ///////////////////////////////////////////////////////////////////////////
307 // Other
308 ///////////////////////////////////////////////////////////////////////////
309
310 /// A filter around an iterator of predicates that makes it yield up
311 /// just trait references.
312 pub struct FilterToTraits<I> {
313     base_iterator: I,
314 }
315
316 impl<I> FilterToTraits<I> {
317     fn new(base: I) -> FilterToTraits<I> {
318         FilterToTraits { base_iterator: base }
319     }
320 }
321
322 impl<'tcx, I: Iterator<Item = PredicateObligation<'tcx>>> Iterator for FilterToTraits<I> {
323     type Item = ty::PolyTraitRef<'tcx>;
324
325     fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
326         while let Some(obligation) = self.base_iterator.next() {
327             if let ty::PredicateKind::Trait(data, _) = obligation.predicate.kind() {
328                 return Some(data.to_poly_trait_ref());
329             }
330         }
331         None
332     }
333
334     fn size_hint(&self) -> (usize, Option<usize>) {
335         let (_, upper) = self.base_iterator.size_hint();
336         (0, upper)
337     }
338 }