Skip to content

Commit 8582f96

Browse files
committed
Cache Predicates' hash within themselves
1 parent 8a75c5a commit 8582f96

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
@@ -141,7 +141,7 @@ pub struct CtxtInterners<'tcx> {
141141
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
142142
region: InternedSet<'tcx, RegionKind<'tcx>>,
143143
poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
144-
predicate: InternedSet<'tcx, PredicateS<'tcx>>,
144+
predicate: InternedSet<'tcx, WithStableHash<PredicateS<'tcx>>>,
145145
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
146146
projs: InternedSet<'tcx, List<ProjectionKind>>,
147147
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
@@ -188,20 +188,8 @@ impl<'tcx> CtxtInterners<'tcx> {
188188
self.type_
189189
.intern(kind, |kind| {
190190
let flags = super::flags::FlagComputation::for_kind(&kind);
191-
192-
// It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them.
193-
// Without incremental, we rarely stable-hash types, so let's not do it proactively.
194-
let stable_hash = if flags.flags.intersects(TypeFlags::NEEDS_INFER)
195-
|| sess.opts.incremental.is_none()
196-
{
197-
Fingerprint::ZERO
198-
} else {
199-
let mut hasher = StableHasher::new();
200-
let mut hcx =
201-
StableHashingContext::new(sess, definitions, cstore, source_span);
202-
kind.hash_stable(&mut hcx, &mut hasher);
203-
hasher.finish()
204-
};
191+
let stable_hash =
192+
self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
205193

206194
let ty_struct = TyS {
207195
kind,
@@ -217,20 +205,54 @@ impl<'tcx> CtxtInterners<'tcx> {
217205
))
218206
}
219207

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

243+
let stable_hash =
244+
self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
245+
227246
let predicate_struct = PredicateS {
228247
kind,
229248
flags: flags.flags,
230249
outer_exclusive_binder: flags.outer_exclusive_binder,
231250
};
232251

233-
InternedInSet(self.arena.alloc(predicate_struct))
252+
InternedInSet(
253+
self.arena
254+
.alloc(WithStableHash { internee: predicate_struct, stable_hash }),
255+
)
234256
})
235257
.0,
236258
))
@@ -2158,23 +2180,25 @@ impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {
21582180
}
21592181
}
21602182

2161-
impl<'tcx> Borrow<Binder<'tcx, PredicateKind<'tcx>>> for InternedInSet<'tcx, PredicateS<'tcx>> {
2183+
impl<'tcx> Borrow<Binder<'tcx, PredicateKind<'tcx>>>
2184+
for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>>
2185+
{
21622186
fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> {
21632187
&self.0.kind
21642188
}
21652189
}
21662190

2167-
impl<'tcx> PartialEq for InternedInSet<'tcx, PredicateS<'tcx>> {
2168-
fn eq(&self, other: &InternedInSet<'tcx, PredicateS<'tcx>>) -> bool {
2191+
impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {
2192+
fn eq(&self, other: &InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>>) -> bool {
21692193
// The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
21702194
// `x == y`.
21712195
self.0.kind == other.0.kind
21722196
}
21732197
}
21742198

2175-
impl<'tcx> Eq for InternedInSet<'tcx, PredicateS<'tcx>> {}
2199+
impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {}
21762200

2177-
impl<'tcx> Hash for InternedInSet<'tcx, PredicateS<'tcx>> {
2201+
impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {
21782202
fn hash<H: Hasher>(&self, s: &mut H) {
21792203
// The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
21802204
self.0.kind.hash(s)
@@ -2373,7 +2397,14 @@ impl<'tcx> TyCtxt<'tcx> {
23732397

23742398
#[inline]
23752399
pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
2376-
self.interners.intern_predicate(binder)
2400+
self.interners.intern_predicate(
2401+
binder,
2402+
self.sess,
2403+
&self.definitions.read(),
2404+
&*self.untracked_resolutions.cstore,
2405+
// This is only used to create a stable hashing context.
2406+
&self.untracked_resolutions.source_span,
2407+
)
23772408
}
23782409

23792410
#[inline]

compiler/rustc_middle/src/ty/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -546,9 +546,9 @@ pub(crate) struct PredicateS<'tcx> {
546546
}
547547

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

553553
impl<'tcx> Predicate<'tcx> {
554554
/// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`.
@@ -627,7 +627,7 @@ impl<'tcx> Predicate<'tcx> {
627627
}
628628
}
629629

630-
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
630+
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for PredicateS<'tcx> {
631631
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
632632
let PredicateS {
633633
ref kind,
@@ -636,7 +636,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
636636
// also contained in `kind`, so no need to hash them.
637637
flags: _,
638638
outer_exclusive_binder: _,
639-
} = self.0.0;
639+
} = self;
640640

641641
kind.hash_stable(hcx, hasher);
642642
}

0 commit comments

Comments
 (0)