1
1
use smallvec:: smallvec;
2
2
3
+ use crate :: traits:: { Obligation , ObligationCause , PredicateObligation } ;
3
4
use rustc_data_structures:: fx:: FxHashSet ;
4
5
use rustc_middle:: ty:: outlives:: Component ;
5
6
use rustc_middle:: ty:: { self , ToPolyTraitRef , ToPredicate , TyCtxt , WithConstness } ;
7
+ use rustc_span:: Span ;
6
8
7
9
pub fn anonymize_predicate < ' tcx > (
8
10
tcx : TyCtxt < ' tcx > ,
@@ -87,7 +89,7 @@ impl<T: AsRef<ty::Predicate<'tcx>>> Extend<T> for PredicateSet<'tcx> {
87
89
/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that
88
90
/// `T: Foo`, then we know that `T: 'static`.
89
91
pub struct Elaborator < ' tcx > {
90
- stack : Vec < ty :: Predicate < ' tcx > > ,
92
+ stack : Vec < PredicateObligation < ' tcx > > ,
91
93
visited : PredicateSet < ' tcx > ,
92
94
}
93
95
@@ -112,35 +114,60 @@ pub fn elaborate_predicates<'tcx>(
112
114
) -> Elaborator < ' tcx > {
113
115
let mut visited = PredicateSet :: new ( tcx) ;
114
116
predicates. retain ( |pred| visited. insert ( pred) ) ;
115
- Elaborator { stack : predicates, visited }
117
+ let obligations: Vec < _ > =
118
+ predicates. into_iter ( ) . map ( |predicate| predicate_obligation ( predicate, None ) ) . collect ( ) ;
119
+ elaborate_obligations ( tcx, obligations)
120
+ }
121
+
122
+ pub fn elaborate_obligations < ' tcx > (
123
+ tcx : TyCtxt < ' tcx > ,
124
+ mut obligations : Vec < PredicateObligation < ' tcx > > ,
125
+ ) -> Elaborator < ' tcx > {
126
+ let mut visited = PredicateSet :: new ( tcx) ;
127
+ obligations. retain ( |obligation| visited. insert ( & obligation. predicate ) ) ;
128
+ Elaborator { stack : obligations, visited }
129
+ }
130
+
131
+ fn predicate_obligation < ' tcx > (
132
+ predicate : ty:: Predicate < ' tcx > ,
133
+ span : Option < Span > ,
134
+ ) -> PredicateObligation < ' tcx > {
135
+ let mut cause = ObligationCause :: dummy ( ) ;
136
+ if let Some ( span) = span {
137
+ cause. span = span;
138
+ }
139
+ Obligation { cause, param_env : ty:: ParamEnv :: empty ( ) , recursion_depth : 0 , predicate }
116
140
}
117
141
118
142
impl Elaborator < ' tcx > {
119
143
pub fn filter_to_traits ( self ) -> FilterToTraits < Self > {
120
144
FilterToTraits :: new ( self )
121
145
}
122
146
123
- fn elaborate ( & mut self , predicate : & ty :: Predicate < ' tcx > ) {
147
+ fn elaborate ( & mut self , obligation : & PredicateObligation < ' tcx > ) {
124
148
let tcx = self . visited . tcx ;
125
- match * predicate {
149
+ match obligation . predicate {
126
150
ty:: Predicate :: Trait ( ref data, _) => {
127
151
// Get predicates declared on the trait.
128
152
let predicates = tcx. super_predicates_of ( data. def_id ( ) ) ;
129
153
130
- let predicates = predicates
131
- . predicates
132
- . iter ( )
133
- . map ( |( pred, _) | pred. subst_supertrait ( tcx, & data. to_poly_trait_ref ( ) ) ) ;
134
- debug ! ( "super_predicates: data={:?} predicates={:?}" , data, predicates. clone( ) ) ;
154
+ let obligations = predicates. predicates . iter ( ) . map ( |( pred, span) | {
155
+ predicate_obligation (
156
+ pred. subst_supertrait ( tcx, & data. to_poly_trait_ref ( ) ) ,
157
+ Some ( * span) ,
158
+ )
159
+ } ) ;
160
+ debug ! ( "super_predicates: data={:?} predicates={:?}" , data, & obligations) ;
135
161
136
162
// Only keep those bounds that we haven't already seen.
137
163
// This is necessary to prevent infinite recursion in some
138
164
// cases. One common case is when people define
139
165
// `trait Sized: Sized { }` rather than `trait Sized { }`.
140
166
let visited = & mut self . visited ;
141
- let predicates = predicates. filter ( |pred| visited. insert ( pred) ) ;
167
+ let obligations =
168
+ obligations. filter ( |obligation| visited. insert ( & obligation. predicate ) ) ;
142
169
143
- self . stack . extend ( predicates ) ;
170
+ self . stack . extend ( obligations ) ;
144
171
}
145
172
ty:: Predicate :: WellFormed ( ..) => {
146
173
// Currently, we do not elaborate WF predicates,
@@ -221,25 +248,26 @@ impl Elaborator<'tcx> {
221
248
None
222
249
}
223
250
} )
224
- . filter ( |p| visited. insert ( p) ) ,
251
+ . filter ( |p| visited. insert ( p) )
252
+ . map ( |p| predicate_obligation ( p, None ) ) ,
225
253
) ;
226
254
}
227
255
}
228
256
}
229
257
}
230
258
231
259
impl Iterator for Elaborator < ' tcx > {
232
- type Item = ty :: Predicate < ' tcx > ;
260
+ type Item = PredicateObligation < ' tcx > ;
233
261
234
262
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
235
263
( self . stack . len ( ) , None )
236
264
}
237
265
238
- fn next ( & mut self ) -> Option < ty :: Predicate < ' tcx > > {
266
+ fn next ( & mut self ) -> Option < Self :: Item > {
239
267
// Extract next item from top-most stack frame, if any.
240
- if let Some ( pred ) = self . stack . pop ( ) {
241
- self . elaborate ( & pred ) ;
242
- Some ( pred )
268
+ if let Some ( obligation ) = self . stack . pop ( ) {
269
+ self . elaborate ( & obligation ) ;
270
+ Some ( obligation )
243
271
} else {
244
272
None
245
273
}
@@ -282,12 +310,12 @@ impl<I> FilterToTraits<I> {
282
310
}
283
311
}
284
312
285
- impl < ' tcx , I : Iterator < Item = ty :: Predicate < ' tcx > > > Iterator for FilterToTraits < I > {
313
+ impl < ' tcx , I : Iterator < Item = PredicateObligation < ' tcx > > > Iterator for FilterToTraits < I > {
286
314
type Item = ty:: PolyTraitRef < ' tcx > ;
287
315
288
316
fn next ( & mut self ) -> Option < ty:: PolyTraitRef < ' tcx > > {
289
- while let Some ( pred ) = self . base_iterator . next ( ) {
290
- if let ty:: Predicate :: Trait ( data, _) = pred {
317
+ while let Some ( obligation ) = self . base_iterator . next ( ) {
318
+ if let ty:: Predicate :: Trait ( data, _) = obligation . predicate {
291
319
return Some ( data. to_poly_trait_ref ( ) ) ;
292
320
}
293
321
}
0 commit comments