/// the ones we have visited.
current_index: ty::DebruijnIndex,
- fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
- fld_t: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a),
- fld_c: &'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx> + 'a),
+ fld_r: Option<&'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a)>,
+ fld_t: Option<&'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a)>,
+ fld_c: Option<&'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx> + 'a)>,
}
impl<'a, 'tcx> BoundVarReplacer<'a, 'tcx> {
- fn new<F, G, H>(tcx: TyCtxt<'tcx>, fld_r: &'a mut F, fld_t: &'a mut G, fld_c: &'a mut H) -> Self
- where
- F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
- G: FnMut(ty::BoundTy) -> Ty<'tcx>,
- H: FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx>,
- {
+ fn new(
+ tcx: TyCtxt<'tcx>,
+ fld_r: Option<&'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a)>,
+ fld_t: Option<&'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a)>,
+ fld_c: Option<&'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx> + 'a)>,
+ ) -> Self {
BoundVarReplacer { tcx, current_index: ty::INNERMOST, fld_r, fld_t, fld_c }
}
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
match *t.kind() {
- ty::Bound(debruijn, bound_ty) => {
- if debruijn == self.current_index {
- let fld_t = &mut self.fld_t;
+ ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => {
+ if let Some(fld_t) = self.fld_t.as_mut() {
let ty = fld_t(bound_ty);
- ty::fold::shift_vars(self.tcx, &ty, self.current_index.as_u32())
- } else {
- t
+ return ty::fold::shift_vars(self.tcx, &ty, self.current_index.as_u32());
}
}
- _ => {
- if !t.has_vars_bound_at_or_above(self.current_index) {
- // Nothing more to substitute.
- t
- } else {
- t.super_fold_with(self)
- }
+ _ if t.has_vars_bound_at_or_above(self.current_index) => {
+ return t.super_fold_with(self);
}
+ _ => {}
}
+ t
}
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
+ if let Some(fld_r) = self.fld_r.as_mut() {
+ let region = fld_r(br);
+ return 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,
+ _ => {}
}
+ r
}
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
- if let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_const), ty } = *ct {
- if debruijn == self.current_index {
- let fld_c = &mut self.fld_c;
- let ct = fld_c(bound_const, ty);
- ty::fold::shift_vars(self.tcx, &ct, self.current_index.as_u32())
- } else {
- ct
+ match *ct {
+ ty::Const { val: ty::ConstKind::Bound(debruijn, bound_const), ty }
+ if debruijn == self.current_index =>
+ {
+ if let Some(fld_c) = self.fld_c.as_mut() {
+ let ct = fld_c(bound_const, ty);
+ return ty::fold::shift_vars(self.tcx, &ct, self.current_index.as_u32());
+ }
}
- } else {
- if !ct.has_vars_bound_at_or_above(self.current_index) {
- // Nothing more to substitute.
- ct
- } else {
- ct.super_fold_with(self)
+ _ if ct.has_vars_bound_at_or_above(self.current_index) => {
+ return ct.super_fold_with(self);
}
+ _ => {}
}
+ ct
}
}
F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
T: TypeFoldable<'tcx>,
{
- // identity for bound types and consts
- let fld_t = |bound_ty| self.mk_ty(ty::Bound(ty::INNERMOST, bound_ty));
- let fld_c = |bound_ct, ty| {
- self.mk_const(ty::Const { val: ty::ConstKind::Bound(ty::INNERMOST, bound_ct), ty })
- };
let mut region_map = BTreeMap::new();
- let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
- let value = self.replace_escaping_bound_vars(value.skip_binder(), real_fld_r, fld_t, fld_c);
+ let mut real_fld_r =
+ |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
+ let value = value.skip_binder();
+ let value = if !value.has_escaping_bound_vars() {
+ value
+ } else {
+ let mut replacer = BoundVarReplacer::new(self, Some(&mut real_fld_r), None, None);
+ value.fold_with(&mut replacer)
+ };
(value, region_map)
}
if !value.has_escaping_bound_vars() {
value
} else {
- let mut replacer = BoundVarReplacer::new(self, &mut fld_r, &mut fld_t, &mut fld_c);
+ let mut replacer =
+ BoundVarReplacer::new(self, Some(&mut fld_r), Some(&mut fld_t), Some(&mut fld_c));
value.fold_with(&mut replacer)
}
}
result
}
+ #[inline]
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
// If the outer-exclusive-binder is *strictly greater* than
// `outer_index`, that means that `t` contains some content
}
}
+ #[inline]
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
// If the region is bound by `outer_index` or anything outside
// of outer index, then it escapes the binders we have
}
}
+ #[inline]
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
if predicate.inner.outer_exclusive_binder > self.outer_index {
ControlFlow::Break(FoundEscapingVars)
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
type BreakTy = FoundFlags;
+ #[inline]
fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> {
debug!(
"HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}",
}
}
+ #[inline]
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = r.type_flags();
debug!("HasTypeFlagsVisitor: r={:?} r.flags={:?} self.flags={:?}", r, flags, self.flags);
}
}
+ #[inline]
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = FlagComputation::for_const(c);
debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
}
}
+ #[inline]
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!(
"HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",