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:
commit
c5d1b3ea96
40 changed files with 254 additions and 186 deletions
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -143,7 +143,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
|
|||
)
|
||||
.emit();
|
||||
|
||||
self.interner().re_error(e)
|
||||
self.interner().mk_re_error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue