@@ -416,19 +416,93 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFolder<'a, 'gcx, 'tcx> {
416
416
}
417
417
418
418
///////////////////////////////////////////////////////////////////////////
419
- // Late-bound region replacer
419
+ // Bound vars replacer
420
420
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 > {
424
423
tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
425
424
426
425
/// As with `RegionFolder`, represents the index of a binder *just outside*
427
426
/// the ones we have visited.
428
427
current_index : ty:: DebruijnIndex ,
429
428
430
429
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
+ }
432
506
}
433
507
434
508
impl < ' a , ' gcx , ' tcx > TyCtxt < ' a , ' gcx , ' tcx > {
@@ -440,16 +514,65 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
440
514
/// same `BoundRegion` will reuse the previous result. A map is
441
515
/// returned at the end with each bound region and the free region
442
516
/// 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 ,
444
522
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 >
449
527
{
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) ;
451
537
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)
453
576
}
454
577
455
578
/// Replace any late-bound regions bound in `value` with
@@ -549,59 +672,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
549
672
}
550
673
}
551
674
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
-
605
675
///////////////////////////////////////////////////////////////////////////
606
676
// Shifter
607
677
//
0 commit comments