@@ -416,19 +416,93 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFolder<'a, 'gcx, 'tcx> {
416416}
417417
418418///////////////////////////////////////////////////////////////////////////
419- // Late-bound region replacer
419+ // Bound vars replacer
420420
421- // Replaces the escaping regions in a type.
422-
423- struct RegionReplacer < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
421+ /// Replaces the escaping bound vars (late bound regions or bound types) in a type.
422+ struct BoundVarReplacer < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > {
424423 tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
425424
426425 /// As with `RegionFolder`, represents the index of a binder *just outside*
427426 /// the ones we have visited.
428427 current_index : ty:: DebruijnIndex ,
429428
430429 fld_r : & ' a mut ( dyn FnMut ( ty:: BoundRegion ) -> ty:: Region < ' tcx > + ' a ) ,
431- map : BTreeMap < ty:: BoundRegion , ty:: Region < ' tcx > >
430+ fld_t : & ' a mut ( dyn FnMut ( ty:: BoundTy ) -> ty:: Ty < ' tcx > + ' a ) ,
431+ }
432+
433+ impl < ' a , ' gcx , ' tcx > BoundVarReplacer < ' a , ' gcx , ' tcx > {
434+ fn new < F , G > (
435+ tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
436+ fld_r : & ' a mut F ,
437+ fld_t : & ' a mut G
438+ ) -> Self
439+ where F : FnMut ( ty:: BoundRegion ) -> ty:: Region < ' tcx > ,
440+ G : FnMut ( ty:: BoundTy ) -> ty:: Ty < ' tcx >
441+ {
442+ BoundVarReplacer {
443+ tcx,
444+ current_index : ty:: INNERMOST ,
445+ fld_r,
446+ fld_t,
447+ }
448+ }
449+ }
450+
451+ impl < ' a , ' gcx , ' tcx > TypeFolder < ' gcx , ' tcx > for BoundVarReplacer < ' a , ' gcx , ' tcx > {
452+ fn tcx < ' b > ( & ' b self ) -> TyCtxt < ' b , ' gcx , ' tcx > { self . tcx }
453+
454+ fn fold_binder < T : TypeFoldable < ' tcx > > ( & mut self , t : & ty:: Binder < T > ) -> ty:: Binder < T > {
455+ self . current_index . shift_in ( 1 ) ;
456+ let t = t. super_fold_with ( self ) ;
457+ self . current_index . shift_out ( 1 ) ;
458+ t
459+ }
460+
461+ fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
462+ match t. sty {
463+ ty:: Bound ( bound_ty) => {
464+ if bound_ty. index == self . current_index {
465+ let fld_t = & mut self . fld_t ;
466+ let ty = fld_t ( bound_ty) ;
467+ ty:: fold:: shift_vars (
468+ self . tcx ,
469+ & ty,
470+ self . current_index . as_u32 ( )
471+ )
472+ } else {
473+ t
474+ }
475+ }
476+ _ => {
477+ if !t. has_vars_bound_at_or_above ( self . current_index ) {
478+ // Nothing more to substitute.
479+ t
480+ } else {
481+ t. super_fold_with ( self )
482+ }
483+ }
484+ }
485+ }
486+
487+ fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
488+ match * r {
489+ ty:: ReLateBound ( debruijn, br) if debruijn == self . current_index => {
490+ let fld_r = & mut self . fld_r ;
491+ let region = fld_r ( br) ;
492+ if let ty:: ReLateBound ( debruijn1, br) = * region {
493+ // If the callback returns a late-bound region,
494+ // that region should always use the INNERMOST
495+ // debruijn index. Then we adjust it to the
496+ // correct depth.
497+ assert_eq ! ( debruijn1, ty:: INNERMOST ) ;
498+ self . tcx . mk_region ( ty:: ReLateBound ( debruijn, br) )
499+ } else {
500+ region
501+ }
502+ }
503+ _ => r
504+ }
505+ }
432506}
433507
434508impl < ' a , ' gcx , ' tcx > TyCtxt < ' a , ' gcx , ' tcx > {
@@ -440,16 +514,65 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
440514 /// same `BoundRegion` will reuse the previous result. A map is
441515 /// returned at the end with each bound region and the free region
442516 /// that replaced it.
443- pub fn replace_late_bound_regions < T , F > ( self ,
517+ ///
518+ /// This method only replaces late bound regions and the result may still
519+ /// contain escaping bound types.
520+ pub fn replace_late_bound_regions < T , F > (
521+ self ,
444522 value : & Binder < T > ,
445- mut f : F )
446- -> ( T , BTreeMap < ty:: BoundRegion , ty:: Region < ' tcx > > )
447- where F : FnMut ( ty:: BoundRegion ) -> ty:: Region < ' tcx > ,
448- T : TypeFoldable < ' tcx > ,
523+ mut fld_r : F
524+ ) -> ( T , BTreeMap < ty:: BoundRegion , ty:: Region < ' tcx > > )
525+ where F : FnMut ( ty:: BoundRegion ) -> ty:: Region < ' tcx > ,
526+ T : TypeFoldable < ' tcx >
449527 {
450- let mut replacer = RegionReplacer :: new ( self , & mut f) ;
528+ let mut map = BTreeMap :: new ( ) ;
529+ let mut real_fldr = |br| {
530+ * map. entry ( br) . or_insert_with ( || fld_r ( br) )
531+ } ;
532+
533+ // identity for bound types
534+ let mut fld_t = |bound_ty| self . mk_ty ( ty:: Bound ( bound_ty) ) ;
535+
536+ let mut replacer = BoundVarReplacer :: new ( self , & mut real_fldr, & mut fld_t) ;
451537 let result = value. skip_binder ( ) . fold_with ( & mut replacer) ;
452- ( result, replacer. map )
538+ ( result, map)
539+ }
540+
541+ /// Replace all escaping bound vars. The `fld_r` closure replaces escaping
542+ /// bound regions while the `flr_t` closure replaces escaping bound types.
543+ pub fn replace_escaping_bound_vars < T , F , G > (
544+ self ,
545+ value : & T ,
546+ mut fld_r : F ,
547+ mut fld_t : G
548+ ) -> T
549+ where F : FnMut ( ty:: BoundRegion ) -> ty:: Region < ' tcx > ,
550+ G : FnMut ( ty:: BoundTy ) -> ty:: Ty < ' tcx > ,
551+ T : TypeFoldable < ' tcx >
552+ {
553+ if !value. has_escaping_bound_vars ( ) {
554+ value. clone ( )
555+ } else {
556+ let mut replacer = BoundVarReplacer :: new ( self , & mut fld_r, & mut fld_t) ;
557+ let result = value. fold_with ( & mut replacer) ;
558+ result
559+ }
560+ }
561+
562+ /// Replace all types or regions bound by the given `Binder`. The `fld_r`
563+ /// closure replaces bound regions while the `flr_t` closure replaces bound
564+ /// types.
565+ pub fn replace_bound_vars < T , F , G > (
566+ self ,
567+ value : & Binder < T > ,
568+ fld_r : F ,
569+ fld_t : G
570+ ) -> T
571+ where F : FnMut ( ty:: BoundRegion ) -> ty:: Region < ' tcx > ,
572+ G : FnMut ( ty:: BoundTy ) -> ty:: Ty < ' tcx > ,
573+ T : TypeFoldable < ' tcx >
574+ {
575+ self . replace_escaping_bound_vars ( value. skip_binder ( ) , fld_r, fld_t)
453576 }
454577
455578 /// Replace any late-bound regions bound in `value` with
@@ -549,59 +672,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
549672 }
550673}
551674
552- impl < ' a , ' gcx , ' tcx > RegionReplacer < ' a , ' gcx , ' tcx > {
553- fn new < F > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > , fld_r : & ' a mut F )
554- -> RegionReplacer < ' a , ' gcx , ' tcx >
555- where F : FnMut ( ty:: BoundRegion ) -> ty:: Region < ' tcx >
556- {
557- RegionReplacer {
558- tcx,
559- current_index : ty:: INNERMOST ,
560- fld_r,
561- map : BTreeMap :: default ( )
562- }
563- }
564- }
565-
566- impl < ' a , ' gcx , ' tcx > TypeFolder < ' gcx , ' tcx > for RegionReplacer < ' a , ' gcx , ' tcx > {
567- fn tcx < ' b > ( & ' b self ) -> TyCtxt < ' b , ' gcx , ' tcx > { self . tcx }
568-
569- fn fold_binder < T : TypeFoldable < ' tcx > > ( & mut self , t : & ty:: Binder < T > ) -> ty:: Binder < T > {
570- self . current_index . shift_in ( 1 ) ;
571- let t = t. super_fold_with ( self ) ;
572- self . current_index . shift_out ( 1 ) ;
573- t
574- }
575-
576- fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
577- if !t. has_vars_bound_at_or_above ( self . current_index ) {
578- return t;
579- }
580-
581- t. super_fold_with ( self )
582- }
583-
584- fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
585- match * r {
586- ty:: ReLateBound ( debruijn, br) if debruijn == self . current_index => {
587- let fld_r = & mut self . fld_r ;
588- let region = * self . map . entry ( br) . or_insert_with ( || fld_r ( br) ) ;
589- if let ty:: ReLateBound ( debruijn1, br) = * region {
590- // If the callback returns a late-bound region,
591- // that region should always use the INNERMOST
592- // debruijn index. Then we adjust it to the
593- // correct depth.
594- assert_eq ! ( debruijn1, ty:: INNERMOST ) ;
595- self . tcx . mk_region ( ty:: ReLateBound ( debruijn, br) )
596- } else {
597- region
598- }
599- }
600- _ => r
601- }
602- }
603- }
604-
605675///////////////////////////////////////////////////////////////////////////
606676// Shifter
607677//
0 commit comments