@@ -15,6 +15,7 @@ use middle::subst::VecPerParamSpace;
1515use middle:: ty;
1616use middle:: typeck;
1717use std:: rc:: Rc ;
18+ use syntax:: ast;
1819use syntax:: owned_slice:: OwnedSlice ;
1920use util:: ppaux:: Repr ;
2021
@@ -449,10 +450,23 @@ impl<'a> TypeFolder for BottomUpFolder<'a> {
449450///////////////////////////////////////////////////////////////////////////
450451// Region folder
451452
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.)
452465pub struct RegionFolder < ' a > {
453466 tcx : & ' a ty:: ctxt ,
454467 fld_t : |ty:: t |: ' a -> ty:: t,
455468 fld_r: |ty:: Region |: ' a -> ty:: Region ,
469+ within_binder_ids: Vec < ast:: NodeId > ,
456470}
457471
458472impl < ' a > RegionFolder < ' a > {
@@ -463,7 +477,8 @@ impl<'a> RegionFolder<'a> {
463477 RegionFolder {
464478 tcx: tcx ,
465479 fld_t : fld_t ,
466- fld_r: fld_r
480+ fld_r : fld_r ,
481+ within_binder_ids : vec ! [ ] ,
467482 }
468483 }
469484
@@ -474,22 +489,53 @@ impl<'a> RegionFolder<'a> {
474489 RegionFolder {
475490 tcx : tcx ,
476491 fld_t : noop ,
477- fld_r: fld_r
492+ fld_r : fld_r ,
493+ within_binder_ids : vec ! [ ] ,
478494 }
479495 }
480496}
481497
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+
482508impl <' a > TypeFolder for RegionFolder < ' a > {
483509 fn tcx < ' a > ( & ' a self ) -> & ' a ty:: ctxt { self . tcx }
484510
485511 fn fold_ty ( & mut self , ty : ty:: t ) -> ty:: t {
486512 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+
487519 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
489527 }
490528
491529 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+ }
494540 }
495541}
0 commit comments