|
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