1
Fork 0

Auto merge of #108020 - nnethercote:opt-mk_region, r=compiler-errors

Optimize `mk_region`

PR #107869 avoiding some interning under `mk_ty` by special-casing `Ty` variants with simple (integer) bodies. This PR does something similar for regions.

r? `@compiler-errors`
This commit is contained in:
bors 2023-02-16 16:11:54 +00:00
commit c5d1b3ea96
40 changed files with 254 additions and 186 deletions

View file

@ -353,7 +353,7 @@ impl<'tcx> CanonicalVarValues<'tcx> {
var: ty::BoundVar::from_usize(i),
kind: ty::BrAnon(i as u32, None),
};
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
tcx.mk_re_late_bound(ty::INNERMOST, br).into()
}
CanonicalVarKind::Const(_, ty)
| CanonicalVarKind::PlaceholderConst(_, ty) => tcx

View file

@ -243,11 +243,20 @@ impl<'tcx> CtxtInterners<'tcx> {
}
}
// For these preinterned values, an alternative would be to have
// variable-length vectors that grow as needed. But that turned out to be
// slightly more complex and no faster.
const NUM_PREINTERNED_TY_VARS: u32 = 100;
const NUM_PREINTERNED_FRESH_TYS: u32 = 20;
const NUM_PREINTERNED_FRESH_INT_TYS: u32 = 3;
const NUM_PREINTERNED_FRESH_FLOAT_TYS: u32 = 3;
// This number may seem high, but it is reached in all but the smallest crates.
const NUM_PREINTERNED_RE_VARS: u32 = 500;
const NUM_PREINTERNED_RE_LATE_BOUNDS_I: u32 = 2;
const NUM_PREINTERNED_RE_LATE_BOUNDS_V: u32 = 20;
pub struct CommonTypes<'tcx> {
pub unit: Ty<'tcx>,
pub bool: Ty<'tcx>,
@ -295,6 +304,14 @@ pub struct CommonLifetimes<'tcx> {
/// Erased region, used outside of type inference.
pub re_erased: Region<'tcx>,
/// Pre-interned `ReVar(ty::RegionVar(n))` for small values of `n`.
pub re_vars: Vec<Region<'tcx>>,
/// Pre-interned values of the form:
/// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })
/// for small values of `i` and `v`.
pub re_late_bounds: Vec<Vec<Region<'tcx>>>,
}
pub struct CommonConsts<'tcx> {
@ -358,7 +375,31 @@ impl<'tcx> CommonLifetimes<'tcx> {
))
};
CommonLifetimes { re_static: mk(ty::ReStatic), re_erased: mk(ty::ReErased) }
let re_vars =
(0..NUM_PREINTERNED_RE_VARS).map(|n| mk(ty::ReVar(ty::RegionVid::from(n)))).collect();
let re_late_bounds = (0..NUM_PREINTERNED_RE_LATE_BOUNDS_I)
.map(|i| {
(0..NUM_PREINTERNED_RE_LATE_BOUNDS_V)
.map(|v| {
mk(ty::ReLateBound(
ty::DebruijnIndex::from(i),
ty::BoundRegion {
var: ty::BoundVar::from(v),
kind: ty::BrAnon(v, None),
},
))
})
.collect()
})
.collect();
CommonLifetimes {
re_static: mk(ty::ReStatic),
re_erased: mk(ty::ReErased),
re_vars,
re_late_bounds,
}
}
}
@ -697,15 +738,15 @@ impl<'tcx> TyCtxt<'tcx> {
/// Constructs a `RegionKind::ReError` lifetime.
#[track_caller]
pub fn re_error(self, reported: ErrorGuaranteed) -> Region<'tcx> {
self.mk_region(ty::ReError(reported))
pub fn mk_re_error(self, reported: ErrorGuaranteed) -> Region<'tcx> {
self.intern_region(ty::ReError(reported))
}
/// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` to ensure it
/// gets used.
#[track_caller]
pub fn re_error_misc(self) -> Region<'tcx> {
self.re_error_with_message(
pub fn mk_re_error_misc(self) -> Region<'tcx> {
self.mk_re_error_with_message(
DUMMY_SP,
"RegionKind::ReError constructed but no error reported",
)
@ -714,9 +755,9 @@ impl<'tcx> TyCtxt<'tcx> {
/// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` with the given
/// `msg` to ensure it gets used.
#[track_caller]
pub fn re_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Region<'tcx> {
pub fn mk_re_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Region<'tcx> {
let reported = self.sess.delay_span_bug(span, msg);
self.re_error(reported)
self.mk_re_error(reported)
}
/// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
@ -1517,7 +1558,7 @@ macro_rules! direct_interners {
}
direct_interners! {
region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>,
region: intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
const_: mk_const_internal(ConstData<'tcx>): Const -> Const<'tcx>,
const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
layout: intern_layout(LayoutS): Layout -> Layout<'tcx>,
@ -1631,13 +1672,6 @@ impl<'tcx> TyCtxt<'tcx> {
})
}
/// Same a `self.mk_region(kind)`, but avoids accessing the interners if
/// `*r == kind`.
#[inline]
pub fn reuse_or_mk_region(self, r: Region<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> {
if *r == kind { r } else { self.mk_region(kind) }
}
// Avoid this in favour of more specific `mk_*` methods, where possible.
#[allow(rustc::usage_of_ty_tykind)]
#[inline]
@ -1966,7 +2000,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
match param.kind {
GenericParamDefKind::Lifetime => {
self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into()
self.mk_re_early_bound(param.to_early_bound_region_data()).into()
}
GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(),
GenericParamDefKind::Const { .. } => self
@ -1998,6 +2032,66 @@ impl<'tcx> TyCtxt<'tcx> {
self.mk_alias(ty::Opaque, self.mk_alias_ty(def_id, substs))
}
#[inline]
pub fn mk_re_early_bound(self, early_bound_region: ty::EarlyBoundRegion) -> Region<'tcx> {
self.intern_region(ty::ReEarlyBound(early_bound_region))
}
#[inline]
pub fn mk_re_late_bound(
self,
debruijn: ty::DebruijnIndex,
bound_region: ty::BoundRegion,
) -> Region<'tcx> {
// Use a pre-interned one when possible.
if let ty::BoundRegion { var, kind: ty::BrAnon(v, None) } = bound_region
&& var.as_u32() == v
&& let Some(inner) = self.lifetimes.re_late_bounds.get(debruijn.as_usize())
&& let Some(re) = inner.get(v as usize).copied()
{
re
} else {
self.intern_region(ty::ReLateBound(debruijn, bound_region))
}
}
#[inline]
pub fn mk_re_free(self, scope: DefId, bound_region: ty::BoundRegionKind) -> Region<'tcx> {
self.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region }))
}
#[inline]
pub fn mk_re_var(self, v: ty::RegionVid) -> Region<'tcx> {
// Use a pre-interned one when possible.
self.lifetimes
.re_vars
.get(v.as_usize())
.copied()
.unwrap_or_else(|| self.intern_region(ty::ReVar(v)))
}
#[inline]
pub fn mk_re_placeholder(self, placeholder: ty::PlaceholderRegion) -> Region<'tcx> {
self.intern_region(ty::RePlaceholder(placeholder))
}
// Avoid this in favour of more specific `mk_re_*` methods, where possible,
// to avoid the cost of the `match`.
pub fn mk_region(self, kind: ty::RegionKind<'tcx>) -> Region<'tcx> {
match kind {
ty::ReEarlyBound(region) => self.mk_re_early_bound(region),
ty::ReLateBound(debruijn, region) => self.mk_re_late_bound(debruijn, region),
ty::ReFree(ty::FreeRegion { scope, bound_region }) => {
self.mk_re_free(scope, bound_region)
}
ty::ReStatic => self.lifetimes.re_static,
ty::ReVar(vid) => self.mk_re_var(vid),
ty::RePlaceholder(region) => self.mk_re_placeholder(region),
ty::ReErased => self.lifetimes.re_erased,
ty::ReError(reported) => self.mk_re_error(reported),
}
}
pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
self.mk_place_elem(place, PlaceElem::Field(f, ty))
}

View file

@ -234,7 +234,7 @@ where
// debruijn index. Then we adjust it to the
// correct depth.
assert_eq!(debruijn1, ty::INNERMOST);
self.tcx.reuse_or_mk_region(region, ty::ReLateBound(debruijn, br))
self.tcx.mk_re_late_bound(debruijn, br)
} else {
region
}
@ -349,10 +349,7 @@ impl<'tcx> TyCtxt<'tcx> {
T: TypeFoldable<'tcx>,
{
self.replace_late_bound_regions_uncached(value, |br| {
self.mk_region(ty::ReFree(ty::FreeRegion {
scope: all_outlive_scope,
bound_region: br.kind,
}))
self.mk_re_free(all_outlive_scope, br.kind)
})
}
@ -365,10 +362,10 @@ impl<'tcx> TyCtxt<'tcx> {
value,
FnMutDelegate {
regions: &mut |r: ty::BoundRegion| {
self.mk_region(ty::ReLateBound(
self.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: shift_bv(r.var), kind: r.kind },
))
)
},
types: &mut |t: ty::BoundTy| {
self.mk_bound(ty::INNERMOST, ty::BoundTy { var: shift_bv(t.var), kind: t.kind })
@ -409,7 +406,7 @@ impl<'tcx> TyCtxt<'tcx> {
})
.expect_region();
let br = ty::BoundRegion { var, kind };
self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
self.tcx.mk_re_late_bound(ty::INNERMOST, br)
}
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
let entry = self.map.entry(bt.var);
@ -479,8 +476,7 @@ impl<'tcx> ir::TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
match *r {
ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
let debruijn = debruijn.shifted_in(self.amount);
let shifted = ty::ReLateBound(debruijn, br);
self.tcx.mk_region(shifted)
self.tcx.mk_re_late_bound(debruijn, br)
}
_ => r,
}
@ -521,7 +517,7 @@ pub fn shift_region<'tcx>(
) -> ty::Region<'tcx> {
match *region {
ty::ReLateBound(debruijn, br) if amount > 0 => {
tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br))
tcx.mk_re_late_bound(debruijn.shifted_in(amount), br)
}
_ => region,
}

View file

@ -100,7 +100,7 @@ impl GenericParamDef {
preceding_substs: &[ty::GenericArg<'tcx>],
) -> ty::GenericArg<'tcx> {
match &self.kind {
ty::GenericParamDefKind::Lifetime => tcx.re_error_misc().into(),
ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(),
ty::GenericParamDefKind::Type { .. } => tcx.ty_error().into(),
ty::GenericParamDefKind::Const { .. } => {
tcx.const_error(tcx.bound_type_of(self.def_id).subst(tcx, preceding_substs)).into()

View file

@ -143,7 +143,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
)
.emit();
self.interner().re_error(e)
self.interner().mk_re_error(e)
}
}
}

View file

@ -182,7 +182,7 @@ impl<'tcx> RegionHighlightMode<'tcx> {
/// Convenience wrapper for `highlighting_region`.
pub fn highlighting_region_vid(&mut self, vid: ty::RegionVid, number: usize) {
self.highlighting_region(self.tcx.mk_region(ty::ReVar(vid)), number)
self.highlighting_region(self.tcx.mk_re_var(vid), number)
}
/// Returns `Some(n)` with the number to use for the given region, if any.
@ -2271,7 +2271,7 @@ impl<'a, 'tcx> ty::ir::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
};
if let ty::ReLateBound(debruijn1, br) = *region {
assert_eq!(debruijn1, ty::INNERMOST);
self.tcx.mk_region(ty::ReLateBound(self.current_index, br))
self.tcx.mk_re_late_bound(self.current_index, br)
} else {
region
}
@ -2383,10 +2383,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name);
return tcx.mk_region(ty::ReLateBound(
return tcx.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
));
);
}
}
@ -2398,10 +2398,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = ty::BrNamed(def_id, name);
return tcx.mk_region(ty::ReLateBound(
return tcx.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
));
);
}
}
@ -2411,10 +2411,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = br.kind;
return tcx.mk_region(ty::ReLateBound(
return tcx.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
));
);
}
}
@ -2426,7 +2426,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
start_or_continue(&mut self, "for<", ", ");
do_continue(&mut self, name);
}
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
tcx.mk_re_late_bound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind })
};
let mut folder = RegionFolder {
tcx,

View file

@ -1187,7 +1187,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for SkipBindersAt<'tcx> {
if index == self.index {
Err(())
} else {
Ok(self.interner().mk_region(ty::ReLateBound(index.shifted_out(1), bv)))
Ok(self.interner().mk_re_late_bound(index.shifted_out(1), bv))
}
} else {
r.try_super_fold_with(self)

View file

@ -564,14 +564,14 @@ impl<'tcx> TyCtxt<'tcx> {
self,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
env_region: ty::RegionKind<'tcx>,
env_region: ty::Region<'tcx>,
) -> Option<Ty<'tcx>> {
let closure_ty = self.mk_closure(closure_def_id, closure_substs);
let closure_kind_ty = closure_substs.as_closure().kind_ty();
let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
let env_ty = match closure_kind {
ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty),
ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty),
ty::ClosureKind::Fn => self.mk_imm_ref(env_region, closure_ty),
ty::ClosureKind::FnMut => self.mk_mut_ref(env_region, closure_ty),
ty::ClosureKind::FnOnce => closure_ty,
};
Some(env_ty)