1
Fork 0

optimize bound vars replacement :3

This commit is contained in:
lcnr 2022-07-28 16:55:15 +02:00
parent c3fce8e937
commit 1436fa9e90
2 changed files with 24 additions and 20 deletions

View file

@ -71,7 +71,7 @@ where
if var_values.var_values.is_empty() { if var_values.var_values.is_empty() {
value value
} else { } else {
let mut delegate = FnMutDelegate { let delegate = FnMutDelegate {
regions: |br: ty::BoundRegion| match var_values.var_values[br.var].unpack() { regions: |br: ty::BoundRegion| match var_values.var_values[br.var].unpack() {
GenericArgKind::Lifetime(l) => l, GenericArgKind::Lifetime(l) => l,
r => bug!("{:?} is a region but value is {:?}", br, r), r => bug!("{:?} is a region but value is {:?}", br, r),
@ -86,6 +86,6 @@ where
}, },
}; };
tcx.replace_escaping_bound_vars_uncached(value, &mut delegate) tcx.replace_escaping_bound_vars_uncached(value, delegate)
} }
} }

View file

@ -400,23 +400,26 @@ where
} }
/// Replaces the escaping bound vars (late bound regions or bound types) in a type. /// Replaces the escaping bound vars (late bound regions or bound types) in a type.
struct BoundVarReplacer<'a, 'tcx> { struct BoundVarReplacer<'tcx, D> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
/// As with `RegionFolder`, represents the index of a binder *just outside* /// As with `RegionFolder`, represents the index of a binder *just outside*
/// the ones we have visited. /// the ones we have visited.
current_index: ty::DebruijnIndex, current_index: ty::DebruijnIndex,
delegate: &'a mut dyn BoundVarReplacerDelegate<'tcx>, delegate: D,
} }
impl<'a, 'tcx> BoundVarReplacer<'a, 'tcx> { impl<'tcx, D: BoundVarReplacerDelegate<'tcx>> BoundVarReplacer<'tcx, D> {
fn new(tcx: TyCtxt<'tcx>, delegate: &'a mut dyn BoundVarReplacerDelegate<'tcx>) -> Self { fn new(tcx: TyCtxt<'tcx>, delegate: D) -> Self {
BoundVarReplacer { tcx, current_index: ty::INNERMOST, delegate } BoundVarReplacer { tcx, current_index: ty::INNERMOST, delegate }
} }
} }
impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> { impl<'tcx, D> TypeFolder<'tcx> for BoundVarReplacer<'tcx, D>
where
D: BoundVarReplacerDelegate<'tcx>,
{
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
self.tcx self.tcx
} }
@ -452,7 +455,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> {
// debruijn index. Then we adjust it to the // debruijn index. Then we adjust it to the
// correct depth. // correct depth.
assert_eq!(debruijn1, ty::INNERMOST); assert_eq!(debruijn1, ty::INNERMOST);
self.tcx.mk_region(ty::ReLateBound(debruijn, br)) self.tcx.reuse_or_mk_region(region, ty::ReLateBound(debruijn, br))
} else { } else {
region region
} }
@ -518,12 +521,12 @@ impl<'tcx> TyCtxt<'tcx> {
if !value.has_escaping_bound_vars() { if !value.has_escaping_bound_vars() {
value value
} else { } else {
let mut delegate = FnMutDelegate { let delegate = FnMutDelegate {
regions: replace_regions, regions: replace_regions,
types: |b| bug!("unexpected bound ty in binder: {b:?}"), types: |b| bug!("unexpected bound ty in binder: {b:?}"),
consts: |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"), consts: |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"),
}; };
let mut replacer = BoundVarReplacer::new(self, &mut delegate); let mut replacer = BoundVarReplacer::new(self, delegate);
value.fold_with(&mut replacer) value.fold_with(&mut replacer)
} }
} }
@ -534,7 +537,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn replace_escaping_bound_vars_uncached<T: TypeFoldable<'tcx>>( pub fn replace_escaping_bound_vars_uncached<T: TypeFoldable<'tcx>>(
self, self,
value: T, value: T,
delegate: &mut impl BoundVarReplacerDelegate<'tcx>, delegate: impl BoundVarReplacerDelegate<'tcx>,
) -> T { ) -> T {
if !value.has_escaping_bound_vars() { if !value.has_escaping_bound_vars() {
value value
@ -550,9 +553,9 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn replace_bound_vars_uncached<T: TypeFoldable<'tcx>>( pub fn replace_bound_vars_uncached<T: TypeFoldable<'tcx>>(
self, self,
value: Binder<'tcx, T>, value: Binder<'tcx, T>,
mut delegate: impl BoundVarReplacerDelegate<'tcx>, delegate: impl BoundVarReplacerDelegate<'tcx>,
) -> T { ) -> T {
self.replace_escaping_bound_vars_uncached(value.skip_binder(), &mut delegate) self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate)
} }
/// Replaces any late-bound regions bound in `value` with /// Replaces any late-bound regions bound in `value` with
@ -580,7 +583,7 @@ impl<'tcx> TyCtxt<'tcx> {
let shift_bv = |bv: ty::BoundVar| ty::BoundVar::from_usize(bv.as_usize() + bound_vars); let shift_bv = |bv: ty::BoundVar| ty::BoundVar::from_usize(bv.as_usize() + bound_vars);
self.replace_escaping_bound_vars_uncached( self.replace_escaping_bound_vars_uncached(
value, value,
&mut FnMutDelegate { FnMutDelegate {
regions: |r: ty::BoundRegion| { regions: |r: ty::BoundRegion| {
self.mk_region(ty::ReLateBound( self.mk_region(ty::ReLateBound(
ty::INNERMOST, ty::INNERMOST,
@ -647,11 +650,11 @@ impl<'tcx> TyCtxt<'tcx> {
where where
T: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>,
{ {
struct Anonymize<'tcx> { struct Anonymize<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
map: FxIndexMap<ty::BoundVar, ty::BoundVariableKind>, map: &'a mut FxIndexMap<ty::BoundVar, ty::BoundVariableKind>,
} }
impl<'tcx> BoundVarReplacerDelegate<'tcx> for Anonymize<'tcx> { impl<'tcx> BoundVarReplacerDelegate<'tcx> for Anonymize<'_, 'tcx> {
fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> { fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> {
let entry = self.map.entry(br.var); let entry = self.map.entry(br.var);
let index = entry.index(); let index = entry.index();
@ -680,9 +683,10 @@ impl<'tcx> TyCtxt<'tcx> {
} }
} }
let mut delegate = Anonymize { tcx: self, map: Default::default() }; let mut map = Default::default();
let inner = self.replace_escaping_bound_vars_uncached(value.skip_binder(), &mut delegate); let delegate = Anonymize { tcx: self, map: &mut map };
let bound_vars = self.mk_bound_variable_kinds(delegate.map.into_values()); let inner = self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate);
let bound_vars = self.mk_bound_variable_kinds(map.into_values());
Binder::bind_with_vars(inner, bound_vars) Binder::bind_with_vars(inner, bound_vars)
} }
} }