|
1 | | -use smallvec::smallvec; |
2 | | - |
3 | 1 | use crate::traits::{self, Obligation, ObligationCauseCode, PredicateObligation}; |
4 | 2 | use rustc_data_structures::fx::FxHashSet; |
5 | 3 | use rustc_middle::ty::ToPolyTraitRef; |
6 | | -use rustc_middle::ty::{self, Ty, TyCtxt, Upcast}; |
| 4 | +use rustc_middle::ty::{self, TyCtxt}; |
7 | 5 | use rustc_span::symbol::Ident; |
8 | 6 | use rustc_span::Span; |
9 | | -use rustc_type_ir::outlives::{push_outlives_components, Component}; |
| 7 | +pub use rustc_type_ir::elaborate::*; |
10 | 8 |
|
11 | 9 | pub fn anonymize_predicate<'tcx>( |
12 | 10 | tcx: TyCtxt<'tcx>, |
@@ -64,50 +62,9 @@ impl<'tcx> Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> { |
64 | 62 | } |
65 | 63 | } |
66 | 64 |
|
67 | | -/////////////////////////////////////////////////////////////////////////// |
68 | | -// `Elaboration` iterator |
69 | | -/////////////////////////////////////////////////////////////////////////// |
70 | | - |
71 | | -/// "Elaboration" is the process of identifying all the predicates that |
72 | | -/// are implied by a source predicate. Currently, this basically means |
73 | | -/// walking the "supertraits" and other similar assumptions. For example, |
74 | | -/// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd` |
75 | | -/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that |
76 | | -/// `T: Foo`, then we know that `T: 'static`. |
77 | | -pub struct Elaborator<'tcx, O> { |
78 | | - stack: Vec<O>, |
79 | | - visited: PredicateSet<'tcx>, |
80 | | - mode: Filter, |
81 | | -} |
82 | | - |
83 | | -enum Filter { |
84 | | - All, |
85 | | - OnlySelf, |
86 | | -} |
87 | | - |
88 | | -/// Describes how to elaborate an obligation into a sub-obligation. |
89 | | -/// |
90 | 65 | /// For [`Obligation`], a sub-obligation is combined with the current obligation's |
91 | | -/// param-env and cause code. For [`ty::Predicate`], none of this is needed, since |
92 | | -/// there is no param-env or cause code to copy over. |
93 | | -pub trait Elaboratable<'tcx> { |
94 | | - fn predicate(&self) -> ty::Predicate<'tcx>; |
95 | | - |
96 | | - // Makes a new `Self` but with a different clause that comes from elaboration. |
97 | | - fn child(&self, clause: ty::Clause<'tcx>) -> Self; |
98 | | - |
99 | | - // Makes a new `Self` but with a different clause and a different cause |
100 | | - // code (if `Self` has one, such as [`PredicateObligation`]). |
101 | | - fn child_with_derived_cause( |
102 | | - &self, |
103 | | - clause: ty::Clause<'tcx>, |
104 | | - span: Span, |
105 | | - parent_trait_pred: ty::PolyTraitPredicate<'tcx>, |
106 | | - index: usize, |
107 | | - ) -> Self; |
108 | | -} |
109 | | - |
110 | | -impl<'tcx> Elaboratable<'tcx> for PredicateObligation<'tcx> { |
| 66 | +/// param-env and cause code. |
| 67 | +impl<'tcx> Elaboratable<TyCtxt<'tcx>> for PredicateObligation<'tcx> { |
111 | 68 | fn predicate(&self) -> ty::Predicate<'tcx> { |
112 | 69 | self.predicate |
113 | 70 | } |
@@ -145,270 +102,6 @@ impl<'tcx> Elaboratable<'tcx> for PredicateObligation<'tcx> { |
145 | 102 | } |
146 | 103 | } |
147 | 104 |
|
148 | | -impl<'tcx> Elaboratable<'tcx> for ty::Predicate<'tcx> { |
149 | | - fn predicate(&self) -> ty::Predicate<'tcx> { |
150 | | - *self |
151 | | - } |
152 | | - |
153 | | - fn child(&self, clause: ty::Clause<'tcx>) -> Self { |
154 | | - clause.as_predicate() |
155 | | - } |
156 | | - |
157 | | - fn child_with_derived_cause( |
158 | | - &self, |
159 | | - clause: ty::Clause<'tcx>, |
160 | | - _span: Span, |
161 | | - _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, |
162 | | - _index: usize, |
163 | | - ) -> Self { |
164 | | - clause.as_predicate() |
165 | | - } |
166 | | -} |
167 | | - |
168 | | -impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) { |
169 | | - fn predicate(&self) -> ty::Predicate<'tcx> { |
170 | | - self.0 |
171 | | - } |
172 | | - |
173 | | - fn child(&self, clause: ty::Clause<'tcx>) -> Self { |
174 | | - (clause.as_predicate(), self.1) |
175 | | - } |
176 | | - |
177 | | - fn child_with_derived_cause( |
178 | | - &self, |
179 | | - clause: ty::Clause<'tcx>, |
180 | | - _span: Span, |
181 | | - _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, |
182 | | - _index: usize, |
183 | | - ) -> Self { |
184 | | - (clause.as_predicate(), self.1) |
185 | | - } |
186 | | -} |
187 | | - |
188 | | -impl<'tcx> Elaboratable<'tcx> for (ty::Clause<'tcx>, Span) { |
189 | | - fn predicate(&self) -> ty::Predicate<'tcx> { |
190 | | - self.0.as_predicate() |
191 | | - } |
192 | | - |
193 | | - fn child(&self, clause: ty::Clause<'tcx>) -> Self { |
194 | | - (clause, self.1) |
195 | | - } |
196 | | - |
197 | | - fn child_with_derived_cause( |
198 | | - &self, |
199 | | - clause: ty::Clause<'tcx>, |
200 | | - _span: Span, |
201 | | - _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, |
202 | | - _index: usize, |
203 | | - ) -> Self { |
204 | | - (clause, self.1) |
205 | | - } |
206 | | -} |
207 | | - |
208 | | -impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> { |
209 | | - fn predicate(&self) -> ty::Predicate<'tcx> { |
210 | | - self.as_predicate() |
211 | | - } |
212 | | - |
213 | | - fn child(&self, clause: ty::Clause<'tcx>) -> Self { |
214 | | - clause |
215 | | - } |
216 | | - |
217 | | - fn child_with_derived_cause( |
218 | | - &self, |
219 | | - clause: ty::Clause<'tcx>, |
220 | | - _span: Span, |
221 | | - _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, |
222 | | - _index: usize, |
223 | | - ) -> Self { |
224 | | - clause |
225 | | - } |
226 | | -} |
227 | | - |
228 | | -pub fn elaborate<'tcx, O: Elaboratable<'tcx>>( |
229 | | - tcx: TyCtxt<'tcx>, |
230 | | - obligations: impl IntoIterator<Item = O>, |
231 | | -) -> Elaborator<'tcx, O> { |
232 | | - let mut elaborator = |
233 | | - Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx), mode: Filter::All }; |
234 | | - elaborator.extend_deduped(obligations); |
235 | | - elaborator |
236 | | -} |
237 | | - |
238 | | -impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { |
239 | | - fn extend_deduped(&mut self, obligations: impl IntoIterator<Item = O>) { |
240 | | - // Only keep those bounds that we haven't already seen. |
241 | | - // This is necessary to prevent infinite recursion in some |
242 | | - // cases. One common case is when people define |
243 | | - // `trait Sized: Sized { }` rather than `trait Sized { }`. |
244 | | - // let visited = &mut self.visited; |
245 | | - self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate()))); |
246 | | - } |
247 | | - |
248 | | - /// Filter to only the supertraits of trait predicates, i.e. only the predicates |
249 | | - /// that have `Self` as their self type, instead of all implied predicates. |
250 | | - pub fn filter_only_self(mut self) -> Self { |
251 | | - self.mode = Filter::OnlySelf; |
252 | | - self |
253 | | - } |
254 | | - |
255 | | - fn elaborate(&mut self, elaboratable: &O) { |
256 | | - let tcx = self.visited.tcx; |
257 | | - |
258 | | - // We only elaborate clauses. |
259 | | - let Some(clause) = elaboratable.predicate().as_clause() else { |
260 | | - return; |
261 | | - }; |
262 | | - |
263 | | - let bound_clause = clause.kind(); |
264 | | - match bound_clause.skip_binder() { |
265 | | - ty::ClauseKind::Trait(data) => { |
266 | | - // Negative trait bounds do not imply any supertrait bounds |
267 | | - if data.polarity != ty::PredicatePolarity::Positive { |
268 | | - return; |
269 | | - } |
270 | | - // Get predicates implied by the trait, or only super predicates if we only care about self predicates. |
271 | | - let predicates = match self.mode { |
272 | | - Filter::All => tcx.explicit_implied_predicates_of(data.def_id()), |
273 | | - Filter::OnlySelf => tcx.explicit_super_predicates_of(data.def_id()), |
274 | | - }; |
275 | | - |
276 | | - let obligations = |
277 | | - predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| { |
278 | | - elaboratable.child_with_derived_cause( |
279 | | - clause.instantiate_supertrait(tcx, bound_clause.rebind(data.trait_ref)), |
280 | | - span, |
281 | | - bound_clause.rebind(data), |
282 | | - index, |
283 | | - ) |
284 | | - }); |
285 | | - debug!(?data, ?obligations, "super_predicates"); |
286 | | - self.extend_deduped(obligations); |
287 | | - } |
288 | | - ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => { |
289 | | - // We know that `T: 'a` for some type `T`. We can |
290 | | - // often elaborate this. For example, if we know that |
291 | | - // `[U]: 'a`, that implies that `U: 'a`. Similarly, if |
292 | | - // we know `&'a U: 'b`, then we know that `'a: 'b` and |
293 | | - // `U: 'b`. |
294 | | - // |
295 | | - // We can basically ignore bound regions here. So for |
296 | | - // example `for<'c> Foo<'a,'c>: 'b` can be elaborated to |
297 | | - // `'a: 'b`. |
298 | | - |
299 | | - // Ignore `for<'a> T: 'a` -- we might in the future |
300 | | - // consider this as evidence that `T: 'static`, but |
301 | | - // I'm a bit wary of such constructions and so for now |
302 | | - // I want to be conservative. --nmatsakis |
303 | | - if r_min.is_bound() { |
304 | | - return; |
305 | | - } |
306 | | - |
307 | | - let mut components = smallvec![]; |
308 | | - push_outlives_components(tcx, ty_max, &mut components); |
309 | | - self.extend_deduped( |
310 | | - components |
311 | | - .into_iter() |
312 | | - .filter_map(|component| match component { |
313 | | - Component::Region(r) => { |
314 | | - if r.is_bound() { |
315 | | - None |
316 | | - } else { |
317 | | - Some(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( |
318 | | - r, r_min, |
319 | | - ))) |
320 | | - } |
321 | | - } |
322 | | - |
323 | | - Component::Param(p) => { |
324 | | - let ty = Ty::new_param(tcx, p.index, p.name); |
325 | | - Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min))) |
326 | | - } |
327 | | - |
328 | | - Component::Placeholder(p) => { |
329 | | - let ty = Ty::new_placeholder(tcx, p); |
330 | | - Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min))) |
331 | | - } |
332 | | - |
333 | | - Component::UnresolvedInferenceVariable(_) => None, |
334 | | - |
335 | | - Component::Alias(alias_ty) => { |
336 | | - // We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`. |
337 | | - // With this, we can deduce that `<Bar as Baz>::Assoc: 'a`. |
338 | | - Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( |
339 | | - alias_ty.to_ty(tcx), |
340 | | - r_min, |
341 | | - ))) |
342 | | - } |
343 | | - |
344 | | - Component::EscapingAlias(_) => { |
345 | | - // We might be able to do more here, but we don't |
346 | | - // want to deal with escaping vars right now. |
347 | | - None |
348 | | - } |
349 | | - }) |
350 | | - .map(|clause| elaboratable.child(bound_clause.rebind(clause).upcast(tcx))), |
351 | | - ); |
352 | | - } |
353 | | - ty::ClauseKind::RegionOutlives(..) => { |
354 | | - // Nothing to elaborate from `'a: 'b`. |
355 | | - } |
356 | | - ty::ClauseKind::WellFormed(..) => { |
357 | | - // Currently, we do not elaborate WF predicates, |
358 | | - // although we easily could. |
359 | | - } |
360 | | - ty::ClauseKind::Projection(..) => { |
361 | | - // Nothing to elaborate in a projection predicate. |
362 | | - } |
363 | | - ty::ClauseKind::ConstEvaluatable(..) => { |
364 | | - // Currently, we do not elaborate const-evaluatable |
365 | | - // predicates. |
366 | | - } |
367 | | - ty::ClauseKind::ConstArgHasType(..) => { |
368 | | - // Nothing to elaborate |
369 | | - } |
370 | | - } |
371 | | - } |
372 | | -} |
373 | | - |
374 | | -impl<'tcx, O: Elaboratable<'tcx>> Iterator for Elaborator<'tcx, O> { |
375 | | - type Item = O; |
376 | | - |
377 | | - fn size_hint(&self) -> (usize, Option<usize>) { |
378 | | - (self.stack.len(), None) |
379 | | - } |
380 | | - |
381 | | - fn next(&mut self) -> Option<Self::Item> { |
382 | | - // Extract next item from top-most stack frame, if any. |
383 | | - if let Some(obligation) = self.stack.pop() { |
384 | | - self.elaborate(&obligation); |
385 | | - Some(obligation) |
386 | | - } else { |
387 | | - None |
388 | | - } |
389 | | - } |
390 | | -} |
391 | | - |
392 | | -/////////////////////////////////////////////////////////////////////////// |
393 | | -// Supertrait iterator |
394 | | -/////////////////////////////////////////////////////////////////////////// |
395 | | - |
396 | | -pub fn supertraits<'tcx>( |
397 | | - tcx: TyCtxt<'tcx>, |
398 | | - trait_ref: ty::PolyTraitRef<'tcx>, |
399 | | -) -> FilterToTraits<Elaborator<'tcx, ty::Clause<'tcx>>> { |
400 | | - elaborate(tcx, [trait_ref.upcast(tcx)]).filter_only_self().filter_to_traits() |
401 | | -} |
402 | | - |
403 | | -pub fn transitive_bounds<'tcx>( |
404 | | - tcx: TyCtxt<'tcx>, |
405 | | - trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>, |
406 | | -) -> FilterToTraits<Elaborator<'tcx, ty::Clause<'tcx>>> { |
407 | | - elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.upcast(tcx))) |
408 | | - .filter_only_self() |
409 | | - .filter_to_traits() |
410 | | -} |
411 | | - |
412 | 105 | /// A specialized variant of `elaborate` that only elaborates trait references that may |
413 | 106 | /// define the given associated item with the name `assoc_name`. It uses the |
414 | 107 | /// `explicit_supertraits_containing_assoc_item` query to avoid enumerating super-predicates that |
@@ -443,37 +136,3 @@ pub fn transitive_bounds_that_define_assoc_item<'tcx>( |
443 | 136 | None |
444 | 137 | }) |
445 | 138 | } |
446 | | - |
447 | | -/////////////////////////////////////////////////////////////////////////// |
448 | | -// Other |
449 | | -/////////////////////////////////////////////////////////////////////////// |
450 | | - |
451 | | -impl<'tcx> Elaborator<'tcx, ty::Clause<'tcx>> { |
452 | | - fn filter_to_traits(self) -> FilterToTraits<Self> { |
453 | | - FilterToTraits { base_iterator: self } |
454 | | - } |
455 | | -} |
456 | | - |
457 | | -/// A filter around an iterator of predicates that makes it yield up |
458 | | -/// just trait references. |
459 | | -pub struct FilterToTraits<I> { |
460 | | - base_iterator: I, |
461 | | -} |
462 | | - |
463 | | -impl<'tcx, I: Iterator<Item = ty::Clause<'tcx>>> Iterator for FilterToTraits<I> { |
464 | | - type Item = ty::PolyTraitRef<'tcx>; |
465 | | - |
466 | | - fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> { |
467 | | - while let Some(pred) = self.base_iterator.next() { |
468 | | - if let Some(data) = pred.as_trait_clause() { |
469 | | - return Some(data.map_bound(|t| t.trait_ref)); |
470 | | - } |
471 | | - } |
472 | | - None |
473 | | - } |
474 | | - |
475 | | - fn size_hint(&self) -> (usize, Option<usize>) { |
476 | | - let (_, upper) = self.base_iterator.size_hint(); |
477 | | - (0, upper) |
478 | | - } |
479 | | -} |
0 commit comments