Skip to content

Commit bddad59

Browse files
committed
Auto merge of rust-lang#94487 - oli-obk:stable_hash_ty, r=fee1-dead
Also cache the stable hash of interned Predicates continuation of rust-lang#94299 This is a small perf improvement and shares more code between `Ty` and `Predicate`
2 parents e0098a5 + 8582f96 commit bddad59

File tree

3 files changed

+59
-28
lines changed

3 files changed

+59
-28
lines changed

compiler/rustc_middle/src/arena.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ macro_rules! arena_types {
8989

9090
// Interned types
9191
[] tys: rustc_data_structures::intern::WithStableHash<rustc_middle::ty::TyS<'tcx>>,
92-
[] predicates: rustc_middle::ty::PredicateS<'tcx>,
92+
[] predicates: rustc_data_structures::intern::WithStableHash<rustc_middle::ty::PredicateS<'tcx>>,
9393
[] consts: rustc_middle::ty::ConstS<'tcx>,
9494

9595
// Note that this deliberately duplicates items in the `rustc_hir::arena`,

compiler/rustc_middle/src/ty/context.rs

+54-23
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ pub struct CtxtInterners<'tcx> {
142142
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
143143
region: InternedSet<'tcx, RegionKind<'tcx>>,
144144
poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
145-
predicate: InternedSet<'tcx, PredicateS<'tcx>>,
145+
predicate: InternedSet<'tcx, WithStableHash<PredicateS<'tcx>>>,
146146
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
147147
projs: InternedSet<'tcx, List<ProjectionKind>>,
148148
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
@@ -190,20 +190,8 @@ impl<'tcx> CtxtInterners<'tcx> {
190190
self.type_
191191
.intern(kind, |kind| {
192192
let flags = super::flags::FlagComputation::for_kind(&kind);
193-
194-
// It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them.
195-
// Without incremental, we rarely stable-hash types, so let's not do it proactively.
196-
let stable_hash = if flags.flags.intersects(TypeFlags::NEEDS_INFER)
197-
|| sess.opts.incremental.is_none()
198-
{
199-
Fingerprint::ZERO
200-
} else {
201-
let mut hasher = StableHasher::new();
202-
let mut hcx =
203-
StableHashingContext::new(sess, definitions, cstore, source_span);
204-
kind.hash_stable(&mut hcx, &mut hasher);
205-
hasher.finish()
206-
};
193+
let stable_hash =
194+
self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
207195

208196
let ty_struct = TyS {
209197
kind,
@@ -219,20 +207,54 @@ impl<'tcx> CtxtInterners<'tcx> {
219207
))
220208
}
221209

210+
fn stable_hash<'a, T: HashStable<StableHashingContext<'a>>>(
211+
&self,
212+
flags: &ty::flags::FlagComputation,
213+
sess: &'a Session,
214+
definitions: &'a rustc_hir::definitions::Definitions,
215+
cstore: &'a CrateStoreDyn,
216+
source_span: &'a IndexVec<LocalDefId, Span>,
217+
val: &T,
218+
) -> Fingerprint {
219+
// It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them.
220+
// Without incremental, we rarely stable-hash types, so let's not do it proactively.
221+
if flags.flags.intersects(TypeFlags::NEEDS_INFER) || sess.opts.incremental.is_none() {
222+
Fingerprint::ZERO
223+
} else {
224+
let mut hasher = StableHasher::new();
225+
let mut hcx = StableHashingContext::new(sess, definitions, cstore, source_span);
226+
val.hash_stable(&mut hcx, &mut hasher);
227+
hasher.finish()
228+
}
229+
}
230+
222231
#[inline(never)]
223-
fn intern_predicate(&self, kind: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
232+
fn intern_predicate(
233+
&self,
234+
kind: Binder<'tcx, PredicateKind<'tcx>>,
235+
sess: &Session,
236+
definitions: &rustc_hir::definitions::Definitions,
237+
cstore: &CrateStoreDyn,
238+
source_span: &IndexVec<LocalDefId, Span>,
239+
) -> Predicate<'tcx> {
224240
Predicate(Interned::new_unchecked(
225241
self.predicate
226242
.intern(kind, |kind| {
227243
let flags = super::flags::FlagComputation::for_predicate(kind);
228244

245+
let stable_hash =
246+
self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
247+
229248
let predicate_struct = PredicateS {
230249
kind,
231250
flags: flags.flags,
232251
outer_exclusive_binder: flags.outer_exclusive_binder,
233252
};
234253

235-
InternedInSet(self.arena.alloc(predicate_struct))
254+
InternedInSet(
255+
self.arena
256+
.alloc(WithStableHash { internee: predicate_struct, stable_hash }),
257+
)
236258
})
237259
.0,
238260
))
@@ -2168,23 +2190,25 @@ impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {
21682190
}
21692191
}
21702192

2171-
impl<'tcx> Borrow<Binder<'tcx, PredicateKind<'tcx>>> for InternedInSet<'tcx, PredicateS<'tcx>> {
2193+
impl<'tcx> Borrow<Binder<'tcx, PredicateKind<'tcx>>>
2194+
for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>>
2195+
{
21722196
fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> {
21732197
&self.0.kind
21742198
}
21752199
}
21762200

2177-
impl<'tcx> PartialEq for InternedInSet<'tcx, PredicateS<'tcx>> {
2178-
fn eq(&self, other: &InternedInSet<'tcx, PredicateS<'tcx>>) -> bool {
2201+
impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {
2202+
fn eq(&self, other: &InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>>) -> bool {
21792203
// The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
21802204
// `x == y`.
21812205
self.0.kind == other.0.kind
21822206
}
21832207
}
21842208

2185-
impl<'tcx> Eq for InternedInSet<'tcx, PredicateS<'tcx>> {}
2209+
impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {}
21862210

2187-
impl<'tcx> Hash for InternedInSet<'tcx, PredicateS<'tcx>> {
2211+
impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {
21882212
fn hash<H: Hasher>(&self, s: &mut H) {
21892213
// The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
21902214
self.0.kind.hash(s)
@@ -2386,7 +2410,14 @@ impl<'tcx> TyCtxt<'tcx> {
23862410

23872411
#[inline]
23882412
pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
2389-
self.interners.intern_predicate(binder)
2413+
self.interners.intern_predicate(
2414+
binder,
2415+
self.sess,
2416+
&self.definitions.read(),
2417+
&*self.untracked_resolutions.cstore,
2418+
// This is only used to create a stable hashing context.
2419+
&self.untracked_resolutions.source_span,
2420+
)
23902421
}
23912422

23922423
#[inline]

compiler/rustc_middle/src/ty/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -548,9 +548,9 @@ pub(crate) struct PredicateS<'tcx> {
548548
}
549549

550550
/// Use this rather than `PredicateS`, whenever possible.
551-
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
551+
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
552552
#[rustc_pass_by_value]
553-
pub struct Predicate<'tcx>(Interned<'tcx, PredicateS<'tcx>>);
553+
pub struct Predicate<'tcx>(Interned<'tcx, WithStableHash<PredicateS<'tcx>>>);
554554

555555
impl<'tcx> Predicate<'tcx> {
556556
/// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`.
@@ -631,7 +631,7 @@ impl<'tcx> Predicate<'tcx> {
631631
}
632632
}
633633

634-
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
634+
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for PredicateS<'tcx> {
635635
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
636636
let PredicateS {
637637
ref kind,
@@ -640,7 +640,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
640640
// also contained in `kind`, so no need to hash them.
641641
flags: _,
642642
outer_exclusive_binder: _,
643-
} = self.0.0;
643+
} = self;
644644

645645
kind.hash_stable(hcx, hasher);
646646
}

0 commit comments

Comments
 (0)