@@ -15,6 +15,7 @@ use middle::subst::VecPerParamSpace;
15
15
use middle:: ty;
16
16
use middle:: typeck;
17
17
use std:: rc:: Rc ;
18
+ use syntax:: ast;
18
19
use syntax:: owned_slice:: OwnedSlice ;
19
20
use util:: ppaux:: Repr ;
20
21
@@ -449,10 +450,23 @@ impl<'a> TypeFolder for BottomUpFolder<'a> {
449
450
///////////////////////////////////////////////////////////////////////////
450
451
// Region folder
451
452
453
+ /// Folds over the substructure of a type, visiting its component
454
+ /// types and all regions that occur *free* within it.
455
+ ///
456
+ /// That is, `ty::t` can contain function or method types that bind
457
+ /// regions at the call site (`ReLateBound`), and occurrences of
458
+ /// regions (aka "lifetimes") that are bound within a type are not
459
+ /// visited by this folder; only regions that occur free will be
460
+ /// visited by `fld_r`.
461
+ ///
462
+ /// (The distinction between "free" and "bound" is represented by
463
+ /// keeping track of each `FnSig` in the lexical context of the
464
+ /// current position of the fold.)
452
465
pub struct RegionFolder < ' a > {
453
466
tcx : & ' a ty:: ctxt ,
454
467
fld_t : |ty:: t |: ' a -> ty:: t,
455
468
fld_r: |ty:: Region |: ' a -> ty:: Region ,
469
+ within_binder_ids: Vec < ast:: NodeId > ,
456
470
}
457
471
458
472
impl < ' a > RegionFolder < ' a > {
@@ -463,7 +477,8 @@ impl<'a> RegionFolder<'a> {
463
477
RegionFolder {
464
478
tcx: tcx ,
465
479
fld_t : fld_t ,
466
- fld_r: fld_r
480
+ fld_r : fld_r ,
481
+ within_binder_ids : vec ! [ ] ,
467
482
}
468
483
}
469
484
@@ -474,22 +489,53 @@ impl<'a> RegionFolder<'a> {
474
489
RegionFolder {
475
490
tcx : tcx ,
476
491
fld_t : noop ,
477
- fld_r: fld_r
492
+ fld_r : fld_r ,
493
+ within_binder_ids : vec ! [ ] ,
478
494
}
479
495
}
480
496
}
481
497
498
+ /// If `ty` has `FnSig` (i.e. closure or fn), return its binder_id;
499
+ /// else None .
500
+ fn opt_binder_id_of_function ( t : ty:: t ) -> Option < ast:: NodeId > {
501
+ match ty:: get ( t ) . sty {
502
+ ty : : ty_closure( ref f) => Some ( f. sig. binder_id) ,
503
+ ty : : ty_bare_fn( ref f) => Some ( f. sig. binder_id) ,
504
+ _ => None ,
505
+ }
506
+ }
507
+
482
508
impl <' a > TypeFolder for RegionFolder < ' a > {
483
509
fn tcx < ' a > ( & ' a self ) -> & ' a ty:: ctxt { self . tcx }
484
510
485
511
fn fold_ty ( & mut self , ty : ty:: t ) -> ty:: t {
486
512
debug ! ( "RegionFolder.fold_ty({})" , ty. repr( self . tcx( ) ) ) ;
513
+ let opt_binder_id = opt_binder_id_of_function ( ty) ;
514
+ match opt_binder_id {
515
+ Some ( binder_id) => self . within_binder_ids . push ( binder_id) ,
516
+ None => { }
517
+ }
518
+
487
519
let t1 = super_fold_ty ( self , ty) ;
488
- ( self . fld_t ) ( t1 )
520
+ let ret = ( self . fld_t ) ( t1) ;
521
+
522
+ if opt_binder_id. is_some ( ) {
523
+ self . within_binder_ids . pop ( ) ;
524
+ }
525
+
526
+ ret
489
527
}
490
528
491
529
fn fold_region ( & mut self , r : ty:: Region ) -> ty:: Region {
492
- debug ! ( "RegionFolder.fold_region({})" , r. repr( self . tcx( ) ) ) ;
493
- ( self . fld_r ) ( r )
530
+ match r {
531
+ ty:: ReLateBound ( binder_id, _) if self . within_binder_ids . contains ( & binder_id) => {
532
+ debug ! ( "RegionFolder.fold_region({}) skipped bound region" , r. repr( self . tcx( ) ) ) ;
533
+ r
534
+ }
535
+ _ => {
536
+ debug ! ( "RegionFolder.fold_region({}) folding free region" , r. repr( self . tcx( ) ) ) ;
537
+ ( self . fld_r ) ( r)
538
+ }
539
+ }
494
540
}
495
541
}
0 commit comments