@@ -66,6 +66,15 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
66
66
fn has_regions_escaping_depth ( & self , depth : u32 ) -> bool {
67
67
self . visit_with ( & mut HasEscapingRegionsVisitor { depth : depth } )
68
68
}
69
+
70
+ /// True if `self` has any late-bound regions that are either
71
+ /// bound by `binder` or bound by some binder outside of `binder`.
72
+ /// If `binder` is `ty::DebruijnIndex::INNERMOST`, this indicates whether
73
+ /// there are any late-bound regions that appear free.
74
+ fn has_regions_bound_by_or_escaping ( & self , binder : ty:: DebruijnIndex ) -> bool {
75
+ self . has_regions_escaping_depth ( binder. depth - 1 )
76
+ }
77
+
69
78
fn has_escaping_regions ( & self ) -> bool {
70
79
self . has_regions_escaping_depth ( 0 )
71
80
}
@@ -207,7 +216,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
207
216
{
208
217
let mut have_bound_regions = false ;
209
218
self . fold_regions ( value, & mut have_bound_regions, |r, d| {
210
- region_set. insert ( self . mk_region ( r. from_depth ( d) ) ) ;
219
+ region_set. insert ( self . mk_region ( r. shifted_out_to_binder ( d) ) ) ;
211
220
r
212
221
} ) ;
213
222
have_bound_regions
@@ -216,13 +225,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
216
225
/// Folds the escaping and free regions in `value` using `f`, and
217
226
/// sets `skipped_regions` to true if any late-bound region was found
218
227
/// and skipped.
219
- pub fn fold_regions < T , F > ( self ,
228
+ pub fn fold_regions < T > (
229
+ self ,
220
230
value : & T ,
221
231
skipped_regions : & mut bool ,
222
- mut f : F )
223
- -> T
224
- where F : FnMut ( ty :: Region < ' tcx > , u32 ) -> ty :: Region < ' tcx > ,
225
- T : TypeFoldable < ' tcx > ,
232
+ mut f : impl FnMut ( ty :: Region < ' tcx > , ty :: DebruijnIndex ) -> ty :: Region < ' tcx > ,
233
+ ) -> T
234
+ where
235
+ T : TypeFoldable < ' tcx > ,
226
236
{
227
237
value. fold_with ( & mut RegionFolder :: new ( self , skipped_regions, & mut f) )
228
238
}
@@ -277,21 +287,32 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
277
287
pub struct RegionFolder < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
278
288
tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
279
289
skipped_regions : & ' a mut bool ,
280
- current_depth : u32 ,
281
- fld_r : & ' a mut ( dyn FnMut ( ty:: Region < ' tcx > , u32 ) -> ty:: Region < ' tcx > + ' a ) ,
290
+
291
+ /// Stores the index of a binder *just outside* the stuff we have
292
+ /// visited. So this begins as INNERMOST; when we pass through a
293
+ /// binder, it is incremented (via `shift_in`).
294
+ current_index : ty:: DebruijnIndex ,
295
+
296
+ /// Callback invokes for each free region. The `DebruijnIndex`
297
+ /// points to the binder *just outside* the ones we have passed
298
+ /// through.
299
+ fold_region_fn : & ' a mut ( dyn FnMut (
300
+ ty:: Region < ' tcx > ,
301
+ ty:: DebruijnIndex ,
302
+ ) -> ty:: Region < ' tcx > + ' a ) ,
282
303
}
283
304
284
305
impl < ' a , ' gcx , ' tcx > RegionFolder < ' a , ' gcx , ' tcx > {
285
- pub fn new < F > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
286
- skipped_regions : & ' a mut bool ,
287
- fld_r : & ' a mut F ) -> RegionFolder < ' a , ' gcx , ' tcx >
288
- where F : FnMut ( ty:: Region < ' tcx > , u32 ) -> ty:: Region < ' tcx >
289
- {
306
+ pub fn new (
307
+ tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
308
+ skipped_regions : & ' a mut bool ,
309
+ fold_region_fn : & ' a mut dyn FnMut ( ty:: Region < ' tcx > , ty :: DebruijnIndex ) -> ty:: Region < ' tcx > ,
310
+ ) -> RegionFolder < ' a , ' gcx , ' tcx > {
290
311
RegionFolder {
291
312
tcx,
292
313
skipped_regions,
293
- current_depth : 1 ,
294
- fld_r ,
314
+ current_index : ty :: DebruijnIndex :: INNERMOST ,
315
+ fold_region_fn ,
295
316
}
296
317
}
297
318
}
@@ -300,24 +321,24 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFolder<'a, 'gcx, 'tcx> {
300
321
fn tcx < ' b > ( & ' b self ) -> TyCtxt < ' b , ' gcx , ' tcx > { self . tcx }
301
322
302
323
fn fold_binder < T : TypeFoldable < ' tcx > > ( & mut self , t : & ty:: Binder < T > ) -> ty:: Binder < T > {
303
- self . current_depth += 1 ;
324
+ self . current_index . shift_in ( 1 ) ;
304
325
let t = t. super_fold_with ( self ) ;
305
- self . current_depth -= 1 ;
326
+ self . current_index . shift_out ( 1 ) ;
306
327
t
307
328
}
308
329
309
330
fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
310
331
match * r {
311
- ty:: ReLateBound ( debruijn, _) if debruijn. depth < self . current_depth => {
312
- debug ! ( "RegionFolder.fold_region({:?}) skipped bound region (current depth={ })" ,
313
- r, self . current_depth ) ;
332
+ ty:: ReLateBound ( debruijn, _) if debruijn < self . current_index => {
333
+ debug ! ( "RegionFolder.fold_region({:?}) skipped bound region (current index={:? })" ,
334
+ r, self . current_index ) ;
314
335
* self . skipped_regions = true ;
315
336
r
316
337
}
317
338
_ => {
318
- debug ! ( "RegionFolder.fold_region({:?}) folding free region (current_depth={ })" ,
319
- r, self . current_depth ) ;
320
- ( self . fld_r ) ( r, self . current_depth )
339
+ debug ! ( "RegionFolder.fold_region({:?}) folding free region (current_index={:? })" ,
340
+ r, self . current_index ) ;
341
+ ( self . fold_region_fn ) ( r, self . current_index )
321
342
}
322
343
}
323
344
}
@@ -330,7 +351,11 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFolder<'a, 'gcx, 'tcx> {
330
351
331
352
struct RegionReplacer < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
332
353
tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
333
- current_depth : u32 ,
354
+
355
+ /// As with `RegionFolder`, represents the index of a binder *just outside*
356
+ /// the ones we have visited.
357
+ current_index : ty:: DebruijnIndex ,
358
+
334
359
fld_r : & ' a mut ( dyn FnMut ( ty:: BoundRegion ) -> ty:: Region < ' tcx > + ' a ) ,
335
360
map : BTreeMap < ty:: BoundRegion , ty:: Region < ' tcx > >
336
361
}
@@ -372,20 +397,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
372
397
} ) . 0
373
398
}
374
399
375
- /// Flattens two binding levels into one. So `for<'a> for<'b> Foo`
400
+ /// Flattens multiple binding levels into one. So `for<'a> for<'b> Foo`
376
401
/// becomes `for<'a,'b> Foo`.
377
402
pub fn flatten_late_bound_regions < T > ( self , bound2_value : & Binder < Binder < T > > )
378
403
-> Binder < T >
379
404
where T : TypeFoldable < ' tcx >
380
405
{
381
406
let bound0_value = bound2_value. skip_binder ( ) . skip_binder ( ) ;
382
- let value = self . fold_regions ( bound0_value, & mut false ,
383
- |region, current_depth| {
407
+ let value = self . fold_regions ( bound0_value, & mut false , |region, current_depth| {
384
408
match * region {
385
- ty:: ReLateBound ( debruijn, br) if debruijn. depth >= current_depth => {
386
- // should be true if no escaping regions from bound2_value
387
- assert ! ( debruijn. depth - current_depth <= 1 ) ;
388
- self . mk_region ( ty:: ReLateBound ( ty:: DebruijnIndex :: new ( current_depth) , br) )
409
+ ty:: ReLateBound ( debruijn, br) => {
410
+ // We assume no regions bound *outside* of the
411
+ // binders in `bound2_value` (nmatsakis added in
412
+ // the course of this PR; seems like a reasonable
413
+ // sanity check though).
414
+ assert ! ( debruijn == current_depth) ;
415
+ self . mk_region ( ty:: ReLateBound ( current_depth, br) )
389
416
}
390
417
_ => {
391
418
region
@@ -446,7 +473,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
446
473
let mut counter = 0 ;
447
474
Binder :: bind ( self . replace_late_bound_regions ( sig, |_| {
448
475
counter += 1 ;
449
- self . mk_region ( ty:: ReLateBound ( ty:: DebruijnIndex :: new ( 1 ) , ty:: BrAnon ( counter) ) )
476
+ self . mk_region ( ty:: ReLateBound ( ty:: DebruijnIndex :: INNERMOST , ty:: BrAnon ( counter) ) )
450
477
} ) . 0 )
451
478
}
452
479
}
@@ -458,7 +485,7 @@ impl<'a, 'gcx, 'tcx> RegionReplacer<'a, 'gcx, 'tcx> {
458
485
{
459
486
RegionReplacer {
460
487
tcx,
461
- current_depth : 1 ,
488
+ current_index : ty :: DebruijnIndex :: INNERMOST ,
462
489
fld_r,
463
490
map : BTreeMap :: default ( )
464
491
}
@@ -469,14 +496,14 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
469
496
fn tcx < ' b > ( & ' b self ) -> TyCtxt < ' b , ' gcx , ' tcx > { self . tcx }
470
497
471
498
fn fold_binder < T : TypeFoldable < ' tcx > > ( & mut self , t : & ty:: Binder < T > ) -> ty:: Binder < T > {
472
- self . current_depth += 1 ;
499
+ self . current_index . shift_in ( 1 ) ;
473
500
let t = t. super_fold_with ( self ) ;
474
- self . current_depth -= 1 ;
501
+ self . current_index . shift_out ( 1 ) ;
475
502
t
476
503
}
477
504
478
505
fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
479
- if !t. has_regions_escaping_depth ( self . current_depth - 1 ) {
506
+ if !t. has_regions_bound_by_or_escaping ( self . current_index ) {
480
507
return t;
481
508
}
482
509
@@ -485,14 +512,15 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
485
512
486
513
fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
487
514
match * r {
488
- ty:: ReLateBound ( debruijn, br) if debruijn. depth == self . current_depth => {
515
+ ty:: ReLateBound ( debruijn, br) if debruijn == self . current_index => {
489
516
let fld_r = & mut self . fld_r ;
490
517
let region = * self . map . entry ( br) . or_insert_with ( || fld_r ( br) ) ;
491
518
if let ty:: ReLateBound ( debruijn1, br) = * region {
492
519
// If the callback returns a late-bound region,
493
- // that region should always use depth 1. Then we
494
- // adjust it to the correct depth.
495
- assert_eq ! ( debruijn1. depth, 1 ) ;
520
+ // that region should always use the INNERMOST
521
+ // debruijn index. Then we adjust it to the
522
+ // correct depth.
523
+ assert_eq ! ( debruijn1, ty:: DebruijnIndex :: INNERMOST ) ;
496
524
self . tcx . mk_region ( ty:: ReLateBound ( debruijn, br) )
497
525
} else {
498
526
region
0 commit comments