From 8582f9644b01bb7d395dd6f206fca17145d6bed7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 14 Mar 2022 16:54:31 +0000 Subject: [PATCH] Cache Predicates' hash within themselves --- compiler/rustc_middle/src/arena.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 77 +++++++++++++++++-------- compiler/rustc_middle/src/ty/mod.rs | 8 +-- 3 files changed, 59 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 7bd4b6c0c2767..e83106b1ee515 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -89,7 +89,7 @@ macro_rules! arena_types { // Interned types [] tys: rustc_data_structures::intern::WithStableHash>, - [] predicates: rustc_middle::ty::PredicateS<'tcx>, + [] predicates: rustc_data_structures::intern::WithStableHash>, [] consts: rustc_middle::ty::ConstS<'tcx>, // Note that this deliberately duplicates items in the `rustc_hir::arena`, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b5327ad0cecc6..b9deaed94088d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -141,7 +141,7 @@ pub struct CtxtInterners<'tcx> { canonical_var_infos: InternedSet<'tcx, List>>, region: InternedSet<'tcx, RegionKind<'tcx>>, poly_existential_predicates: InternedSet<'tcx, List>>, - predicate: InternedSet<'tcx, PredicateS<'tcx>>, + predicate: InternedSet<'tcx, WithStableHash>>, predicates: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, @@ -188,20 +188,8 @@ impl<'tcx> CtxtInterners<'tcx> { self.type_ .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_kind(&kind); - - // It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them. - // Without incremental, we rarely stable-hash types, so let's not do it proactively. - let stable_hash = if flags.flags.intersects(TypeFlags::NEEDS_INFER) - || sess.opts.incremental.is_none() - { - Fingerprint::ZERO - } else { - let mut hasher = StableHasher::new(); - let mut hcx = - StableHashingContext::new(sess, definitions, cstore, source_span); - kind.hash_stable(&mut hcx, &mut hasher); - hasher.finish() - }; + let stable_hash = + self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); let ty_struct = TyS { kind, @@ -217,20 +205,54 @@ impl<'tcx> CtxtInterners<'tcx> { )) } + fn stable_hash<'a, T: HashStable>>( + &self, + flags: &ty::flags::FlagComputation, + sess: &'a Session, + definitions: &'a rustc_hir::definitions::Definitions, + cstore: &'a CrateStoreDyn, + source_span: &'a IndexVec, + val: &T, + ) -> Fingerprint { + // It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them. + // Without incremental, we rarely stable-hash types, so let's not do it proactively. + if flags.flags.intersects(TypeFlags::NEEDS_INFER) || sess.opts.incremental.is_none() { + Fingerprint::ZERO + } else { + let mut hasher = StableHasher::new(); + let mut hcx = StableHashingContext::new(sess, definitions, cstore, source_span); + val.hash_stable(&mut hcx, &mut hasher); + hasher.finish() + } + } + #[inline(never)] - fn intern_predicate(&self, kind: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> { + fn intern_predicate( + &self, + kind: Binder<'tcx, PredicateKind<'tcx>>, + sess: &Session, + definitions: &rustc_hir::definitions::Definitions, + cstore: &CrateStoreDyn, + source_span: &IndexVec, + ) -> Predicate<'tcx> { Predicate(Interned::new_unchecked( self.predicate .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_predicate(kind); + let stable_hash = + self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); + let predicate_struct = PredicateS { kind, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, }; - InternedInSet(self.arena.alloc(predicate_struct)) + InternedInSet( + self.arena + .alloc(WithStableHash { internee: predicate_struct, stable_hash }), + ) }) .0, )) @@ -2158,23 +2180,25 @@ impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash>> { } } -impl<'tcx> Borrow>> for InternedInSet<'tcx, PredicateS<'tcx>> { +impl<'tcx> Borrow>> + for InternedInSet<'tcx, WithStableHash>> +{ fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> { &self.0.kind } } -impl<'tcx> PartialEq for InternedInSet<'tcx, PredicateS<'tcx>> { - fn eq(&self, other: &InternedInSet<'tcx, PredicateS<'tcx>>) -> bool { +impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash>> { + fn eq(&self, other: &InternedInSet<'tcx, WithStableHash>>) -> bool { // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals // `x == y`. self.0.kind == other.0.kind } } -impl<'tcx> Eq for InternedInSet<'tcx, PredicateS<'tcx>> {} +impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash>> {} -impl<'tcx> Hash for InternedInSet<'tcx, PredicateS<'tcx>> { +impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash>> { fn hash(&self, s: &mut H) { // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. self.0.kind.hash(s) @@ -2373,7 +2397,14 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> { - self.interners.intern_predicate(binder) + self.interners.intern_predicate( + binder, + self.sess, + &self.definitions.read(), + &*self.untracked_resolutions.cstore, + // This is only used to create a stable hashing context. + &self.untracked_resolutions.source_span, + ) } #[inline] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9d778ff2fb6e3..a4c67ad0f3d4d 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -546,9 +546,9 @@ pub(crate) struct PredicateS<'tcx> { } /// Use this rather than `PredicateS`, whenever possible. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] -pub struct Predicate<'tcx>(Interned<'tcx, PredicateS<'tcx>>); +pub struct Predicate<'tcx>(Interned<'tcx, WithStableHash>>); impl<'tcx> Predicate<'tcx> { /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. @@ -627,7 +627,7 @@ impl<'tcx> Predicate<'tcx> { } } -impl<'a, 'tcx> HashStable> for Predicate<'tcx> { +impl<'a, 'tcx> HashStable> for PredicateS<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let PredicateS { ref kind, @@ -636,7 +636,7 @@ impl<'a, 'tcx> HashStable> for Predicate<'tcx> { // also contained in `kind`, so no need to hash them. flags: _, outer_exclusive_binder: _, - } = self.0.0; + } = self; kind.hash_stable(hcx, hasher); }