diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs index bd62f30372ef7..009b5d5340afe 100644 --- a/compiler/rustc_data_structures/src/intern.rs +++ b/compiler/rustc_data_structures/src/intern.rs @@ -115,34 +115,41 @@ pub trait InternedHashingContext { fn with_def_path_and_no_spans(&mut self, f: impl FnOnce(&mut Self)); } +/// A helper type that you can wrap round your own type in order to automatically +/// cache the stable hash on creation and not recompute it whenever the stable hash +/// of the type is computed. +/// This is only done in incremental mode. You can also opt out of caching by using +/// StableHash::ZERO for the hash, in which case the hash gets computed each time. +/// This is useful if you have values that you intern but never (can?) use for stable +/// hashing. #[derive(Copy, Clone)] -pub struct InTy { +pub struct WithStableHash { pub internee: T, pub stable_hash: Fingerprint, } -impl PartialEq for InTy { +impl PartialEq for WithStableHash { #[inline] fn eq(&self, other: &Self) -> bool { self.internee.eq(&other.internee) } } -impl Eq for InTy {} +impl Eq for WithStableHash {} -impl PartialOrd for InTy { - fn partial_cmp(&self, other: &InTy) -> Option { +impl PartialOrd for WithStableHash { + fn partial_cmp(&self, other: &WithStableHash) -> Option { Some(self.internee.cmp(&other.internee)) } } -impl Ord for InTy { - fn cmp(&self, other: &InTy) -> Ordering { +impl Ord for WithStableHash { + fn cmp(&self, other: &WithStableHash) -> Ordering { self.internee.cmp(&other.internee) } } -impl Deref for InTy { +impl Deref for WithStableHash { type Target = T; #[inline] @@ -151,14 +158,14 @@ impl Deref for InTy { } } -impl Hash for InTy { +impl Hash for WithStableHash { #[inline] fn hash(&self, s: &mut H) { self.internee.hash(s) } } -impl, CTX: InternedHashingContext> HashStable for InTy { +impl, CTX: InternedHashingContext> HashStable for WithStableHash { fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) { // No cached hash available. This can only mean that incremental is disabled. diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 5141d5beb7d45..7c90cbb9092b8 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -87,7 +87,7 @@ macro_rules! arena_types { [] hir_id_set: rustc_hir::HirIdSet, // Interned types - [] tys: rustc_data_structures::intern::InTy>, + [] tys: rustc_data_structures::intern::WithStableHash>, [] predicates: rustc_middle::ty::PredicateS<'tcx>, [] consts: rustc_middle::ty::ConstS<'tcx>, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index bc077a673f362..acca24a79f4d8 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -26,7 +26,7 @@ use crate::ty::{ use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::intern::{InTy, Interned}; +use rustc_data_structures::intern::{Interned, WithStableHash}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; @@ -105,7 +105,7 @@ pub struct CtxtInterners<'tcx> { // Specifically use a speedy hash algorithm for these hash sets, since // they're accessed quite often. - type_: InternedSet<'tcx, InTy>>, + type_: InternedSet<'tcx, WithStableHash>>, substs: InternedSet<'tcx, InternalSubsts<'tcx>>, canonical_var_infos: InternedSet<'tcx, List>>, region: InternedSet<'tcx, RegionKind>, @@ -180,7 +180,9 @@ impl<'tcx> CtxtInterners<'tcx> { outer_exclusive_binder: flags.outer_exclusive_binder, }; - InternedInSet(self.arena.alloc(InTy { internee: ty_struct, stable_hash })) + InternedInSet( + self.arena.alloc(WithStableHash { internee: ty_struct, stable_hash }), + ) }) .0, )) @@ -2047,23 +2049,23 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> { } #[allow(rustc::usage_of_ty_tykind)] -impl<'tcx> Borrow> for InternedInSet<'tcx, InTy>> { +impl<'tcx> Borrow> for InternedInSet<'tcx, WithStableHash>> { fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { &self.0.kind } } -impl<'tcx> PartialEq for InternedInSet<'tcx, InTy>> { - fn eq(&self, other: &InternedInSet<'tcx, InTy>>) -> 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, InTy>> {} +impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash>> {} -impl<'tcx> Hash for InternedInSet<'tcx, InTy>> { +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) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 482460c0fe9f8..a4a9fef4515c0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -31,7 +31,7 @@ use crate::ty::util::Discr; use rustc_ast as ast; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; -use rustc_data_structures::intern::{InTy, Interned}; +use rustc_data_structures::intern::{Interned, WithStableHash}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; @@ -439,15 +439,22 @@ crate struct TyS<'tcx> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(TyS<'_>, 40); +// We are actually storing a stable hash cache next to the type, so let's +// also check the full size +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +static_assert_size!(WithStableHash>, 56); + /// Use this rather than `TyS`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_diagnostic_item = "Ty"] #[rustc_pass_by_value] -pub struct Ty<'tcx>(Interned<'tcx, InTy>>); +pub struct Ty<'tcx>(Interned<'tcx, WithStableHash>>); // Statics only used for internal testing. -pub static BOOL_TY: Ty<'static> = - Ty(Interned::new_unchecked(&InTy { internee: BOOL_TYS, stable_hash: Fingerprint::ZERO })); +pub static BOOL_TY: Ty<'static> = Ty(Interned::new_unchecked(&WithStableHash { + internee: BOOL_TYS, + stable_hash: Fingerprint::ZERO, +})); const BOOL_TYS: TyS<'static> = TyS { kind: ty::Bool, flags: TypeFlags::empty(), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 7e0b0ace8c0a8..1a843a4732309 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3,7 +3,7 @@ use crate::ty::subst::{GenericArg, GenericArgKind, Subst}; use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable}; use rustc_apfloat::ieee::{Double, Single}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::intern::{InTy, Interned}; +use rustc_data_structures::intern::{Interned, WithStableHash}; use rustc_data_structures::sso::SsoHashSet; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; @@ -1266,13 +1266,13 @@ pub trait PrettyPrinter<'tcx>: ty::Ref( _, Ty(Interned( - InTy { + WithStableHash { internee: ty::TyS { kind: ty::Array( Ty(Interned( - InTy { + WithStableHash { internee: ty::TyS { kind: ty::Uint(ty::UintTy::U8), .. }, .. @@ -1452,7 +1452,10 @@ pub trait PrettyPrinter<'tcx>: ConstValue::Slice { data, start, end }, ty::Ref( _, - Ty(Interned(InTy { internee: ty::TyS { kind: ty::Slice(t), .. }, .. }, _)), + Ty(Interned( + WithStableHash { internee: ty::TyS { kind: ty::Slice(t), .. }, .. }, + _, + )), _, ), ) if *t == u8_type => { @@ -1467,7 +1470,7 @@ pub trait PrettyPrinter<'tcx>: ConstValue::Slice { data, start, end }, ty::Ref( _, - Ty(Interned(InTy { internee: ty::TyS { kind: ty::Str, .. }, .. }, _)), + Ty(Interned(WithStableHash { internee: ty::TyS { kind: ty::Str, .. }, .. }, _)), _, ), ) => { diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 50357877c0afc..46b938ea93baa 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -6,7 +6,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeVisitor} use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; -use rustc_data_structures::intern::{InTy, Interned}; +use rustc_data_structures::intern::{Interned, WithStableHash}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{self, Decodable, Encodable}; @@ -85,7 +85,7 @@ impl<'tcx> GenericArgKind<'tcx> { GenericArgKind::Type(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const InTy> as usize) + (TYPE_TAG, ty.0.0 as *const WithStableHash> as usize) } GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. @@ -154,7 +154,7 @@ impl<'tcx> GenericArg<'tcx> { &*((ptr & !TAG_MASK) as *const ty::RegionKind), ))), TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const InTy>), + &*((ptr & !TAG_MASK) as *const WithStableHash>), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index a5cc730813fef..29a388538792c 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -13,7 +13,7 @@ use rustc_apfloat::Float as _; use rustc_ast as ast; use rustc_attr::{self as attr, SignedInt, UnsignedInt}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::intern::{InTy, Interned}; +use rustc_data_structures::intern::{Interned, WithStableHash}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; @@ -427,7 +427,9 @@ impl<'tcx> TyCtxt<'tcx> { !impl_generics.region_param(ebr, self).pure_wrt_drop } GenericArgKind::Type(Ty(Interned( - InTy { internee: ty::TyS { kind: ty::Param(ref pt), .. }, .. }, + WithStableHash { + internee: ty::TyS { kind: ty::Param(ref pt), .. }, .. + }, _, ))) => !impl_generics.type_param(pt, self).pure_wrt_drop, GenericArgKind::Const(Const(Interned(