Skip to content

Commit 41fe75e

Browse files
committed
Auto merge of #118189 - compiler-errors:cache-flags-for-const, r=nnethercote
Cache flags for `ty::Const` Not sure if this has been attempted yet, but worth a shot. It does make the code simpler in `rustc_type_ir`, since we can assume that consts have a `flags` method that is no-cost. r? `@ghost`
2 parents eab8c7d + 4ec6857 commit 41fe75e

File tree

9 files changed

+92
-43
lines changed

9 files changed

+92
-43
lines changed

compiler/rustc_infer/src/infer/canonical/canonicalizer.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use crate::infer::canonical::{
99
Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, OriginalQueryValues,
1010
};
1111
use crate::infer::InferCtxt;
12-
use rustc_middle::ty::flags::FlagComputation;
1312
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
1413
use rustc_middle::ty::GenericArg;
1514
use rustc_middle::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
@@ -550,8 +549,11 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
550549
_ => {}
551550
}
552551

553-
let flags = FlagComputation::for_const(ct);
554-
if flags.intersects(self.needs_canonical_flags) { ct.super_fold_with(self) } else { ct }
552+
if ct.flags().intersects(self.needs_canonical_flags) {
553+
ct.super_fold_with(self)
554+
} else {
555+
ct
556+
}
555557
}
556558
}
557559

compiler/rustc_middle/src/arena.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ macro_rules! arena_types {
9494

9595
// Interned types
9696
[] tys: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::TyKind<'tcx>>,
97-
[] consts: rustc_middle::ty::ConstData<'tcx>,
97+
[] consts: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::ConstData<'tcx>>,
9898

9999
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
100100
// since we need to allocate this type on both the `rustc_hir` arena

compiler/rustc_middle/src/ty/consts.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_hir as hir;
77
use rustc_hir::def::{DefKind, Res};
88
use rustc_hir::def_id::LocalDefId;
99
use rustc_macros::HashStable;
10+
use rustc_type_ir::{TypeFlags, WithCachedTypeInfo};
1011

1112
mod int;
1213
mod kind;
@@ -23,7 +24,7 @@ use super::sty::ConstKind;
2324
/// Use this rather than `ConstData`, whenever possible.
2425
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
2526
#[rustc_pass_by_value]
26-
pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>);
27+
pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>);
2728

2829
/// Typed constant value.
2930
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]
@@ -46,6 +47,16 @@ impl<'tcx> Const<'tcx> {
4647
self.0.kind.clone()
4748
}
4849

50+
#[inline]
51+
pub fn flags(self) -> TypeFlags {
52+
self.0.flags
53+
}
54+
55+
#[inline]
56+
pub fn outer_exclusive_binder(self) -> ty::DebruijnIndex {
57+
self.0.outer_exclusive_binder
58+
}
59+
4960
#[inline]
5061
pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
5162
tcx.mk_ct_from_kind(kind, ty)

compiler/rustc_middle/src/ty/context.rs

+44-8
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ pub struct CtxtInterners<'tcx> {
151151
clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
152152
projs: InternedSet<'tcx, List<ProjectionKind>>,
153153
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
154-
const_: InternedSet<'tcx, ConstData<'tcx>>,
154+
const_: InternedSet<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>,
155155
const_allocation: InternedSet<'tcx, Allocation>,
156156
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
157157
layout: InternedSet<'tcx, LayoutS<FieldIdx, VariantIdx>>,
@@ -212,6 +212,32 @@ impl<'tcx> CtxtInterners<'tcx> {
212212
))
213213
}
214214

215+
/// Interns a const. (Use `mk_*` functions instead, where possible.)
216+
#[allow(rustc::usage_of_ty_tykind)]
217+
#[inline(never)]
218+
fn intern_const(
219+
&self,
220+
data: ty::ConstData<'tcx>,
221+
sess: &Session,
222+
untracked: &Untracked,
223+
) -> Const<'tcx> {
224+
Const(Interned::new_unchecked(
225+
self.const_
226+
.intern(data, |data: ConstData<'_>| {
227+
let flags = super::flags::FlagComputation::for_const(&data.kind, data.ty);
228+
let stable_hash = self.stable_hash(&flags, sess, untracked, &data);
229+
230+
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
231+
internee: data,
232+
stable_hash,
233+
flags: flags.flags,
234+
outer_exclusive_binder: flags.outer_exclusive_binder,
235+
}))
236+
})
237+
.0,
238+
))
239+
}
240+
215241
fn stable_hash<'a, T: HashStable<StableHashingContext<'a>>>(
216242
&self,
217243
flags: &ty::flags::FlagComputation,
@@ -418,11 +444,17 @@ impl<'tcx> CommonLifetimes<'tcx> {
418444
}
419445

420446
impl<'tcx> CommonConsts<'tcx> {
421-
fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonConsts<'tcx> {
447+
fn new(
448+
interners: &CtxtInterners<'tcx>,
449+
types: &CommonTypes<'tcx>,
450+
sess: &Session,
451+
untracked: &Untracked,
452+
) -> CommonConsts<'tcx> {
422453
let mk_const = |c| {
423-
Const(Interned::new_unchecked(
424-
interners.const_.intern(c, |c| InternedInSet(interners.arena.alloc(c))).0,
425-
))
454+
interners.intern_const(
455+
c, sess, // This is only used to create a stable hashing context.
456+
untracked,
457+
)
426458
};
427459

428460
CommonConsts {
@@ -714,7 +746,7 @@ impl<'tcx> TyCtxt<'tcx> {
714746
let interners = CtxtInterners::new(arena);
715747
let common_types = CommonTypes::new(&interners, s, &untracked);
716748
let common_lifetimes = CommonLifetimes::new(&interners);
717-
let common_consts = CommonConsts::new(&interners, &common_types);
749+
let common_consts = CommonConsts::new(&interners, &common_types, s, &untracked);
718750

719751
GlobalCtxt {
720752
sess: s,
@@ -1533,7 +1565,6 @@ macro_rules! direct_interners {
15331565
// crate only, and have a corresponding `mk_` function.
15341566
direct_interners! {
15351567
region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
1536-
const_: intern_const(ConstData<'tcx>): Const -> Const<'tcx>,
15371568
const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
15381569
layout: pub mk_layout(LayoutS<FieldIdx, VariantIdx>): Layout -> Layout<'tcx>,
15391570
adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
@@ -1710,7 +1741,12 @@ impl<'tcx> TyCtxt<'tcx> {
17101741

17111742
#[inline]
17121743
pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
1713-
self.intern_const(ty::ConstData { kind, ty })
1744+
self.interners.intern_const(
1745+
ty::ConstData { kind, ty },
1746+
self.sess,
1747+
// This is only used to create a stable hashing context.
1748+
&self.untracked,
1749+
)
17141750
}
17151751

17161752
// Avoid this in favour of more specific `Ty::new_*` methods, where possible.

compiler/rustc_middle/src/ty/flags.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ impl FlagComputation {
2828
result
2929
}
3030

31-
pub fn for_const(c: ty::Const<'_>) -> TypeFlags {
31+
pub fn for_const(c: &ty::ConstKind<'_>, t: Ty<'_>) -> FlagComputation {
3232
let mut result = FlagComputation::new();
33-
result.add_const(c);
34-
result.flags
33+
result.add_const_kind(c);
34+
result.add_ty(t);
35+
result
3536
}
3637

3738
fn add_flags(&mut self, flags: TypeFlags) {
@@ -297,8 +298,12 @@ impl FlagComputation {
297298
}
298299

299300
fn add_const(&mut self, c: ty::Const<'_>) {
300-
self.add_ty(c.ty());
301-
match c.kind() {
301+
self.add_flags(c.flags());
302+
self.add_exclusive_binder(c.outer_exclusive_binder());
303+
}
304+
305+
fn add_const_kind(&mut self, c: &ty::ConstKind<'_>) {
306+
match *c {
302307
ty::ConstKind::Unevaluated(uv) => {
303308
self.add_args(uv.args);
304309
self.add_flags(TypeFlags::HAS_CT_PROJECTION);

compiler/rustc_middle/src/ty/generic_args.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ impl<'tcx> GenericArgKind<'tcx> {
7070
GenericArgKind::Const(ct) => {
7171
// Ensure we can use the tag bits.
7272
assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
73-
(CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
73+
(CONST_TAG, ct.0.0 as *const WithCachedTypeInfo<ty::ConstData<'tcx>> as usize)
7474
}
7575
};
7676

@@ -136,7 +136,7 @@ impl<'tcx> GenericArg<'tcx> {
136136
&*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
137137
))),
138138
CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked(
139-
&*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>),
139+
&*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::ConstData<'tcx>>),
140140
))),
141141
_ => intrinsics::unreachable(),
142142
}

compiler/rustc_middle/src/ty/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@ impl<'tcx> Term<'tcx> {
900900
&*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
901901
))),
902902
CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
903-
&*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>),
903+
&*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::ConstData<'tcx>>),
904904
))),
905905
_ => core::intrinsics::unreachable(),
906906
}
@@ -967,7 +967,7 @@ impl<'tcx> TermKind<'tcx> {
967967
TermKind::Const(ct) => {
968968
// Ensure we can use the tag bits.
969969
assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
970-
(CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
970+
(CONST_TAG, ct.0.0 as *const WithCachedTypeInfo<ty::ConstData<'tcx>> as usize)
971971
}
972972
};
973973

compiler/rustc_middle/src/ty/visit.rs

+11-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
1+
use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags};
22
use rustc_errors::ErrorGuaranteed;
33

44
use rustc_data_structures::fx::FxHashSet;
@@ -440,16 +440,15 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasEscapingVarsVisitor {
440440
}
441441

442442
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
443-
// we don't have a `visit_infer_const` callback, so we have to
444-
// hook in here to catch this case (annoying...), but
445-
// otherwise we do want to remember to visit the rest of the
446-
// const, as it has types/regions embedded in a lot of other
447-
// places.
448-
match ct.kind() {
449-
ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => {
450-
ControlFlow::Break(FoundEscapingVars)
451-
}
452-
_ => ct.super_visit_with(self),
443+
// If the outer-exclusive-binder is *strictly greater* than
444+
// `outer_index`, that means that `ct` contains some content
445+
// bound at `outer_index` or above (because
446+
// `outer_exclusive_binder` is always 1 higher than the
447+
// content in `t`). Therefore, `t` has some escaping vars.
448+
if ct.outer_exclusive_binder() > self.outer_index {
449+
ControlFlow::Break(FoundEscapingVars)
450+
} else {
451+
ControlFlow::Continue(())
453452
}
454453
}
455454

@@ -529,9 +528,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor {
529528
#[inline]
530529
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
531530
// Note: no `super_visit_with` call.
532-
let flags = FlagComputation::for_const(c);
533-
trace!(r.flags=?flags);
534-
if flags.intersects(self.flags) {
531+
if c.flags().intersects(self.flags) {
535532
ControlFlow::Break(FoundFlags)
536533
} else {
537534
ControlFlow::Continue(())

compiler/rustc_trait_selection/src/traits/query/normalize.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,12 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor {
160160
}
161161

162162
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
163-
match ct.kind() {
164-
ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => {
165-
self.escaping =
166-
self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize());
167-
ControlFlow::Continue(())
168-
}
169-
_ => ct.super_visit_with(self),
163+
if ct.outer_exclusive_binder() > self.outer_index {
164+
self.escaping = self
165+
.escaping
166+
.max(ct.outer_exclusive_binder().as_usize() - self.outer_index.as_usize());
170167
}
168+
ControlFlow::Continue(())
171169
}
172170
}
173171

0 commit comments

Comments
 (0)