+ fld_t: &'a mut (dyn FnMut(ty::BoundTy) -> ty::Ty<'tcx> + 'a),
+}
+
+impl<'a, 'gcx, 'tcx> BoundVarReplacer<'a, 'gcx, 'tcx> {
+ fn new<F, G>(
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ fld_r: &'a mut F,
+ fld_t: &'a mut G
+ ) -> Self
+ where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
+ G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>
+ {
+ BoundVarReplacer {
+ tcx,
+ current_index: ty::INNERMOST,
+ fld_r,
+ fld_t,
+ }
+ }
+}
+
+impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for BoundVarReplacer<'a, 'gcx, 'tcx> {
+ fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
+
+ fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
+ self.current_index.shift_in(1);
+ let t = t.super_fold_with(self);
+ self.current_index.shift_out(1);
+ t
+ }
+
+ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+ match t.sty {
+ ty::Bound(bound_ty) => {
+ if bound_ty.index == self.current_index {
+ let fld_t = &mut self.fld_t;
+ let ty = fld_t(bound_ty);
+ ty::fold::shift_vars(
+ self.tcx,
+ &ty,
+ self.current_index.as_u32()
+ )
+ } else {
+ t
+ }
+ }
+ _ => {
+ if !t.has_vars_bound_at_or_above(self.current_index) {
+ // Nothing more to substitute.
+ t
+ } else {
+ t.super_fold_with(self)
+ }
+ }
+ }
+ }
+
+ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+ match *r {
+ ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
+ let fld_r = &mut self.fld_r;
+ let region = fld_r(br);
+ if let ty::ReLateBound(debruijn1, br) = *region {
+ // If the callback returns a late-bound region,
+ // that region should always use the INNERMOST
+ // debruijn index. Then we adjust it to the
+ // correct depth.
+ assert_eq!(debruijn1, ty::INNERMOST);
+ self.tcx.mk_region(ty::ReLateBound(debruijn, br))
+ } else {
+ region
+ }
+ }
+ _ => r
+ }
+ }