| 
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,7 @@ 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 |  | -/// 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> {  | 
 | 65 | +impl<'tcx> Elaboratable<TyCtxt<'tcx>> for PredicateObligation<'tcx> {  | 
111 | 66 |     fn predicate(&self) -> ty::Predicate<'tcx> {  | 
112 | 67 |         self.predicate  | 
113 | 68 |     }  | 
@@ -145,270 +100,6 @@ impl<'tcx> Elaboratable<'tcx> for PredicateObligation<'tcx> {  | 
145 | 100 |     }  | 
146 | 101 | }  | 
147 | 102 | 
 
  | 
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 | 103 | /// A specialized variant of `elaborate` that only elaborates trait references that may  | 
413 | 104 | /// define the given associated item with the name `assoc_name`. It uses the  | 
414 | 105 | /// `explicit_supertraits_containing_assoc_item` query to avoid enumerating super-predicates that  | 
@@ -443,37 +134,3 @@ pub fn transitive_bounds_that_define_assoc_item<'tcx>(  | 
443 | 134 |         None  | 
444 | 135 |     })  | 
445 | 136 | }  | 
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