]> git.lizzy.rs Git - rust.git/blob - src/librustc_infer/traits/util.rs
fix elaborate for predicates with unbound variables
[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, 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.kind();
14     let new = match kind {
15         ty::PredicateKind::ForAll(binder) => {
16             ty::PredicateKind::ForAll(tcx.anonymize_late_bound_regions(binder))
17         }
18         &ty::PredicateKind::Trait(data, constness) => ty::PredicateKind::Trait(data, constness),
19
20         &ty::PredicateKind::RegionOutlives(data) => ty::PredicateKind::RegionOutlives(data),
21
22         &ty::PredicateKind::TypeOutlives(data) => ty::PredicateKind::TypeOutlives(data),
23
24         &ty::PredicateKind::Projection(data) => ty::PredicateKind::Projection(data),
25
26         &ty::PredicateKind::WellFormed(data) => ty::PredicateKind::WellFormed(data),
27
28         &ty::PredicateKind::ObjectSafe(data) => ty::PredicateKind::ObjectSafe(data),
29
30         &ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
31             ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind)
32         }
33
34         &ty::PredicateKind::Subtype(data) => ty::PredicateKind::Subtype(data),
35
36         &ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
37             ty::PredicateKind::ConstEvaluatable(def_id, substs)
38         }
39
40         &ty::PredicateKind::ConstEquate(c1, c2) => ty::PredicateKind::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<'tcx, Self> {
149         FilterToTraits::new(self.visited.tcx, self)
150     }
151
152     fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
153         let tcx = self.visited.tcx;
154
155         match obligation.predicate.ignore_qualifiers(tcx).skip_binder().kind() {
156             ty::PredicateKind::ForAll(_) => {
157                 bug!("unexpected predicate: {:?}", obligation.predicate)
158             }
159             ty::PredicateKind::Trait(data, _) => {
160                 // Get predicates declared on the trait.
161                 let predicates = tcx.super_predicates_of(data.def_id());
162
163                 let obligations = predicates.predicates.iter().map(|&(pred, span)| {
164                     predicate_obligation(
165                         pred.subst_supertrait(tcx, &ty::Binder::bind(data.trait_ref)),
166                         Some(span),
167                     )
168                 });
169                 debug!("super_predicates: data={:?}", data);
170
171                 // Only keep those bounds that we haven't already seen.
172                 // This is necessary to prevent infinite recursion in some
173                 // cases. One common case is when people define
174                 // `trait Sized: Sized { }` rather than `trait Sized { }`.
175                 let visited = &mut self.visited;
176                 let obligations = obligations.filter(|o| visited.insert(o.predicate));
177
178                 self.stack.extend(obligations);
179             }
180             ty::PredicateKind::WellFormed(..) => {
181                 // Currently, we do not elaborate WF predicates,
182                 // although we easily could.
183             }
184             ty::PredicateKind::ObjectSafe(..) => {
185                 // Currently, we do not elaborate object-safe
186                 // predicates.
187             }
188             ty::PredicateKind::Subtype(..) => {
189                 // Currently, we do not "elaborate" predicates like `X <: Y`,
190                 // though conceivably we might.
191             }
192             ty::PredicateKind::Projection(..) => {
193                 // Nothing to elaborate in a projection predicate.
194             }
195             ty::PredicateKind::ClosureKind(..) => {
196                 // Nothing to elaborate when waiting for a closure's kind to be inferred.
197             }
198             ty::PredicateKind::ConstEvaluatable(..) => {
199                 // Currently, we do not elaborate const-evaluatable
200                 // predicates.
201             }
202             ty::PredicateKind::ConstEquate(..) => {
203                 // Currently, we do not elaborate const-equate
204                 // predicates.
205             }
206             ty::PredicateKind::RegionOutlives(..) => {
207                 // Nothing to elaborate from `'a: 'b`.
208             }
209             ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
210                 // We know that `T: 'a` for some type `T`. We can
211                 // often elaborate this. For example, if we know that
212                 // `[U]: 'a`, that implies that `U: 'a`. Similarly, if
213                 // we know `&'a U: 'b`, then we know that `'a: 'b` and
214                 // `U: 'b`.
215                 //
216                 // We can basically ignore bound regions here. So for
217                 // example `for<'c> Foo<'a,'c>: 'b` can be elaborated to
218                 // `'a: 'b`.
219
220                 // Ignore `for<'a> T: 'a` -- we might in the future
221                 // consider this as evidence that `T: 'static`, but
222                 // I'm a bit wary of such constructions and so for now
223                 // I want to be conservative. --nmatsakis
224                 if r_min.is_late_bound() {
225                     return;
226                 }
227
228                 let visited = &mut self.visited;
229                 let mut components = smallvec![];
230                 tcx.push_outlives_components(ty_max, &mut components);
231                 self.stack.extend(
232                     components
233                         .into_iter()
234                         .filter_map(|component| match component {
235                             Component::Region(r) => {
236                                 if r.is_late_bound() {
237                                     None
238                                 } else {
239                                     Some(ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(
240                                         r, r_min,
241                                     )))
242                                 }
243                             }
244
245                             Component::Param(p) => {
246                                 let ty = tcx.mk_ty_param(p.index, p.name);
247                                 Some(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
248                                     ty, r_min,
249                                 )))
250                             }
251
252                             Component::UnresolvedInferenceVariable(_) => None,
253
254                             Component::Projection(_) | Component::EscapingProjection(_) => {
255                                 // We can probably do more here. This
256                                 // corresponds to a case like `<T as
257                                 // Foo<'a>>::U: 'b`.
258                                 None
259                             }
260                         })
261                         .map(|predicate_kind| predicate_kind.to_predicate(tcx))
262                         .filter(|&predicate| visited.insert(predicate))
263                         .map(|predicate| predicate_obligation(predicate, None)),
264                 );
265             }
266         }
267     }
268 }
269
270 impl Iterator for Elaborator<'tcx> {
271     type Item = PredicateObligation<'tcx>;
272
273     fn size_hint(&self) -> (usize, Option<usize>) {
274         (self.stack.len(), None)
275     }
276
277     fn next(&mut self) -> Option<Self::Item> {
278         // Extract next item from top-most stack frame, if any.
279         if let Some(obligation) = self.stack.pop() {
280             self.elaborate(&obligation);
281             Some(obligation)
282         } else {
283             None
284         }
285     }
286 }
287
288 ///////////////////////////////////////////////////////////////////////////
289 // Supertrait iterator
290 ///////////////////////////////////////////////////////////////////////////
291
292 pub type Supertraits<'tcx> = FilterToTraits<'tcx, Elaborator<'tcx>>;
293
294 pub fn supertraits<'tcx>(
295     tcx: TyCtxt<'tcx>,
296     trait_ref: ty::PolyTraitRef<'tcx>,
297 ) -> Supertraits<'tcx> {
298     elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
299 }
300
301 pub fn transitive_bounds<'tcx>(
302     tcx: TyCtxt<'tcx>,
303     bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
304 ) -> Supertraits<'tcx> {
305     elaborate_trait_refs(tcx, bounds).filter_to_traits()
306 }
307
308 ///////////////////////////////////////////////////////////////////////////
309 // Other
310 ///////////////////////////////////////////////////////////////////////////
311
312 /// A filter around an iterator of predicates that makes it yield up
313 /// just trait references.
314 pub struct FilterToTraits<'tcx, I> {
315     tcx: TyCtxt<'tcx>,
316     base_iterator: I,
317 }
318
319 impl<'tcx, I> FilterToTraits<'tcx, I> {
320     fn new(tcx: TyCtxt<'tcx>, base: I) -> FilterToTraits<'tcx, I> {
321         FilterToTraits { tcx, base_iterator: base }
322     }
323 }
324
325 impl<'tcx, I: Iterator<Item = PredicateObligation<'tcx>>> Iterator for FilterToTraits<'tcx, I> {
326     type Item = ty::PolyTraitRef<'tcx>;
327
328     fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
329         while let Some(obligation) = self.base_iterator.next() {
330             if let Some(data) = obligation.predicate.to_opt_poly_trait_ref(self.tcx) {
331                 return Some(data);
332             }
333         }
334         None
335     }
336
337     fn size_hint(&self) -> (usize, Option<usize>) {
338         let (_, upper) = self.base_iterator.size_hint();
339         (0, upper)
340     }
341 }