@@ -14,6 +14,7 @@ use infer::{GenericKind, VerifyBound};
14
14
use traits;
15
15
use ty:: subst:: { Subst , Substs } ;
16
16
use ty:: { self , Ty , TyCtxt } ;
17
+ use util:: captures:: Captures ;
17
18
18
19
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
19
20
/// obligation into a series of `'a: 'b` constraints and "verifys", as
@@ -65,21 +66,15 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
65
66
66
67
// Start with anything like `T: 'a` we can scrape from the
67
68
// environment
68
- let param_bounds =
69
- self . declared_generic_bounds_from_env ( GenericKind :: Param ( param_ty ) )
70
- . into_iter ( ) ;
69
+ let param_bounds = self . declared_generic_bounds_from_env ( GenericKind :: Param ( param_ty ) )
70
+ . into_iter ( )
71
+ . map ( |outlives| outlives . 1 ) ;
71
72
72
73
// Add in the default bound of fn body that applies to all in
73
74
// scope type parameters:
74
- let param_bounds =
75
- param_bounds
76
- . chain ( self . implicit_region_bound ) ;
75
+ let param_bounds = param_bounds. chain ( self . implicit_region_bound ) ;
77
76
78
- VerifyBound :: AnyBound (
79
- param_bounds
80
- . map ( |r| VerifyBound :: OutlivedBy ( r) )
81
- . collect ( )
82
- )
77
+ VerifyBound :: AnyBound ( param_bounds. map ( |r| VerifyBound :: OutlivedBy ( r) ) . collect ( ) )
83
78
}
84
79
85
80
/// Given a projection like `T::Item`, searches the environment
@@ -98,7 +93,7 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
98
93
pub fn projection_approx_declared_bounds_from_env (
99
94
& self ,
100
95
projection_ty : ty:: ProjectionTy < ' tcx > ,
101
- ) -> Vec < ty:: Region < ' tcx > > {
96
+ ) -> Vec < ty:: OutlivesPredicate < Ty < ' tcx > , ty :: Region < ' tcx > > > {
102
97
let projection_ty = GenericKind :: Projection ( projection_ty) . to_ty ( self . tcx ) ;
103
98
let erased_projection_ty = self . tcx . erase_regions ( & projection_ty) ;
104
99
self . declared_generic_bounds_from_env_with_compare_fn ( |ty| {
@@ -117,31 +112,42 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
117
112
pub fn projection_declared_bounds_from_trait (
118
113
& self ,
119
114
projection_ty : ty:: ProjectionTy < ' tcx > ,
120
- ) -> Vec < ty:: Region < ' tcx > > {
115
+ ) -> impl Iterator < Item = ty:: Region < ' tcx > > + ' cx + Captures < ' gcx > {
121
116
self . declared_projection_bounds_from_trait ( projection_ty)
122
117
}
123
118
124
119
pub fn projection_bound ( & self , projection_ty : ty:: ProjectionTy < ' tcx > ) -> VerifyBound < ' tcx > {
125
120
debug ! ( "projection_bound(projection_ty={:?})" , projection_ty) ;
126
121
122
+ let projection_ty_as_ty =
123
+ self . tcx . mk_projection ( projection_ty. item_def_id , projection_ty. substs ) ;
124
+
127
125
// Search the env for where clauses like `P: 'a`.
128
- let env_bounds =
129
- self . declared_generic_bounds_from_env ( GenericKind :: Projection ( projection_ty) )
130
- . into_iter ( ) ;
126
+ let env_bounds = self . projection_approx_declared_bounds_from_env ( projection_ty)
127
+ . into_iter ( )
128
+ . map ( |ty:: OutlivesPredicate ( ty, r) | {
129
+ let vb = VerifyBound :: OutlivedBy ( r) ;
130
+ if ty == projection_ty_as_ty {
131
+ // Micro-optimize if this is an exact match (this
132
+ // occurs often when there are no region variables
133
+ // involved).
134
+ vb
135
+ } else {
136
+ VerifyBound :: IfEq ( ty, Box :: new ( vb) )
137
+ }
138
+ } ) ;
131
139
132
140
// Extend with bounds that we can find from the trait.
133
- let trait_bounds =
134
- self . projection_declared_bounds_from_trait ( projection_ty )
135
- . into_iter ( ) ;
141
+ let trait_bounds = self . projection_declared_bounds_from_trait ( projection_ty )
142
+ . into_iter ( )
143
+ . map ( |r| VerifyBound :: OutlivedBy ( r ) ) ;
136
144
137
145
// see the extensive comment in projection_must_outlive
138
146
let ty = self . tcx
139
147
. mk_projection ( projection_ty. item_def_id , projection_ty. substs ) ;
140
148
let recursive_bound = self . recursive_type_bound ( ty) ;
141
149
142
- VerifyBound :: AnyBound (
143
- env_bounds. chain ( trait_bounds) . map ( |r| VerifyBound :: OutlivedBy ( r) ) . collect ( )
144
- ) . or ( recursive_bound)
150
+ VerifyBound :: AnyBound ( env_bounds. chain ( trait_bounds) . collect ( ) ) . or ( recursive_bound)
145
151
}
146
152
147
153
fn recursive_type_bound ( & self , ty : Ty < ' tcx > ) -> VerifyBound < ' tcx > {
@@ -151,11 +157,12 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
151
157
152
158
let mut regions = ty. regions ( ) ;
153
159
regions. retain ( |r| !r. is_late_bound ( ) ) ; // ignore late-bound regions
154
- bounds. push (
155
- VerifyBound :: AllBounds (
156
- regions. into_iter ( ) . map ( |r| VerifyBound :: OutlivedBy ( r) ) . collect ( )
157
- )
158
- ) ;
160
+ bounds. push ( VerifyBound :: AllBounds (
161
+ regions
162
+ . into_iter ( )
163
+ . map ( |r| VerifyBound :: OutlivedBy ( r) )
164
+ . collect ( ) ,
165
+ ) ) ;
159
166
160
167
// remove bounds that must hold, since they are not interesting
161
168
bounds. retain ( |b| !b. must_hold ( ) ) ;
@@ -176,15 +183,15 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
176
183
fn declared_generic_bounds_from_env (
177
184
& self ,
178
185
generic : GenericKind < ' tcx > ,
179
- ) -> Vec < ty:: Region < ' tcx > > {
186
+ ) -> Vec < ty:: OutlivesPredicate < Ty < ' tcx > , ty :: Region < ' tcx > > > {
180
187
let generic_ty = generic. to_ty ( self . tcx ) ;
181
188
self . declared_generic_bounds_from_env_with_compare_fn ( |ty| ty == generic_ty)
182
189
}
183
190
184
191
fn declared_generic_bounds_from_env_with_compare_fn (
185
192
& self ,
186
193
compare_ty : impl Fn ( Ty < ' tcx > ) -> bool ,
187
- ) -> Vec < ty:: Region < ' tcx > > {
194
+ ) -> Vec < ty:: OutlivesPredicate < Ty < ' tcx > , ty :: Region < ' tcx > > > {
188
195
let tcx = self . tcx ;
189
196
190
197
// To start, collect bounds from user environment. Note that
@@ -212,14 +219,23 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
212
219
"declared_generic_bounds_from_env_with_compare_fn: region_bound_pair = {:?}" ,
213
220
( r, p)
214
221
) ;
215
- if compare_ty ( p. to_ty ( tcx) ) {
216
- Some ( r)
222
+ let p_ty = p. to_ty ( tcx) ;
223
+ if compare_ty ( p_ty) {
224
+ Some ( ty:: OutlivesPredicate ( p_ty, r) )
217
225
} else {
218
226
None
219
227
}
220
228
} ) ;
221
229
222
- param_bounds. chain ( from_region_bound_pairs) . collect ( )
230
+ param_bounds
231
+ . chain ( from_region_bound_pairs)
232
+ . inspect ( |bound| {
233
+ debug ! (
234
+ "declared_generic_bounds_from_env_with_compare_fn: result predicate = {:?}" ,
235
+ bound
236
+ )
237
+ } )
238
+ . collect ( )
223
239
}
224
240
225
241
/// Given a projection like `<T as Foo<'x>>::Bar`, returns any bounds
@@ -237,13 +253,11 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
237
253
fn declared_projection_bounds_from_trait (
238
254
& self ,
239
255
projection_ty : ty:: ProjectionTy < ' tcx > ,
240
- ) -> Vec < ty:: Region < ' tcx > > {
256
+ ) -> impl Iterator < Item = ty:: Region < ' tcx > > + ' cx + Captures < ' gcx > {
241
257
debug ! ( "projection_bounds(projection_ty={:?})" , projection_ty) ;
242
- let mut bounds = self . region_bounds_declared_on_associated_item ( projection_ty. item_def_id ) ;
243
- for r in & mut bounds {
244
- * r = r. subst ( self . tcx , projection_ty. substs ) ;
245
- }
246
- bounds
258
+ let tcx = self . tcx ;
259
+ self . region_bounds_declared_on_associated_item ( projection_ty. item_def_id )
260
+ . map ( move |r| r. subst ( tcx, projection_ty. substs ) )
247
261
}
248
262
249
263
/// Given the def-id of an associated item, returns any region
@@ -279,7 +293,7 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
279
293
fn region_bounds_declared_on_associated_item (
280
294
& self ,
281
295
assoc_item_def_id : DefId ,
282
- ) -> Vec < ty:: Region < ' tcx > > {
296
+ ) -> impl Iterator < Item = ty:: Region < ' tcx > > + ' cx + Captures < ' gcx > {
283
297
let tcx = self . tcx ;
284
298
let assoc_item = tcx. associated_item ( assoc_item_def_id) ;
285
299
let trait_def_id = assoc_item. container . assert_trait ( ) ;
@@ -289,7 +303,7 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
289
303
self . collect_outlives_from_predicate_list (
290
304
move |ty| ty == identity_proj,
291
305
traits:: elaborate_predicates ( tcx, trait_predicates. predicates ) ,
292
- ) . collect ( )
306
+ ) . map ( |b| b . 1 )
293
307
}
294
308
295
309
/// Searches through a predicate list for a predicate `T: 'a`.
@@ -302,12 +316,11 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
302
316
& self ,
303
317
compare_ty : impl Fn ( Ty < ' tcx > ) -> bool ,
304
318
predicates : impl IntoIterator < Item = impl AsRef < ty:: Predicate < ' tcx > > > ,
305
- ) -> impl Iterator < Item = ty:: Region < ' tcx > > {
319
+ ) -> impl Iterator < Item = ty:: OutlivesPredicate < Ty < ' tcx > , ty :: Region < ' tcx > > > {
306
320
predicates
307
321
. into_iter ( )
308
322
. filter_map ( |p| p. as_ref ( ) . to_opt_type_outlives ( ) )
309
323
. filter_map ( |p| p. no_late_bound_regions ( ) )
310
324
. filter ( move |p| compare_ty ( p. 0 ) )
311
- . map ( |p| p. 1 )
312
325
}
313
326
}
0 commit comments