From 3d31e5c9810227ceb56d6d3a5228ca28b1aca890 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 25 Nov 2022 16:30:23 +0000 Subject: [PATCH 1/6] s/WithStableHash/WithCachedTypeInfo/ --- compiler/rustc_data_structures/src/intern.rs | 20 ++++++------- compiler/rustc_middle/src/arena.rs | 4 +-- compiler/rustc_middle/src/ty/context.rs | 30 ++++++++++---------- compiler/rustc_middle/src/ty/mod.rs | 29 ++++++++++--------- compiler/rustc_middle/src/ty/subst.rs | 6 ++-- 5 files changed, 45 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs index 11cbff8ea6a..9985aeaab57 100644 --- a/compiler/rustc_data_structures/src/intern.rs +++ b/compiler/rustc_data_structures/src/intern.rs @@ -118,33 +118,33 @@ where /// This is useful if you have values that you intern but never (can?) use for stable /// hashing. #[derive(Copy, Clone)] -pub struct WithStableHash { +pub struct WithCachedTypeInfo { pub internee: T, pub stable_hash: Fingerprint, } -impl PartialEq for WithStableHash { +impl PartialEq for WithCachedTypeInfo { #[inline] fn eq(&self, other: &Self) -> bool { self.internee.eq(&other.internee) } } -impl Eq for WithStableHash {} +impl Eq for WithCachedTypeInfo {} -impl PartialOrd for WithStableHash { - fn partial_cmp(&self, other: &WithStableHash) -> Option { +impl PartialOrd for WithCachedTypeInfo { + fn partial_cmp(&self, other: &WithCachedTypeInfo) -> Option { Some(self.internee.cmp(&other.internee)) } } -impl Ord for WithStableHash { - fn cmp(&self, other: &WithStableHash) -> Ordering { +impl Ord for WithCachedTypeInfo { + fn cmp(&self, other: &WithCachedTypeInfo) -> Ordering { self.internee.cmp(&other.internee) } } -impl Deref for WithStableHash { +impl Deref for WithCachedTypeInfo { type Target = T; #[inline] @@ -153,7 +153,7 @@ impl Deref for WithStableHash { } } -impl Hash for WithStableHash { +impl Hash for WithCachedTypeInfo { #[inline] fn hash(&self, s: &mut H) { if self.stable_hash != Fingerprint::ZERO { @@ -164,7 +164,7 @@ impl Hash for WithStableHash { } } -impl, CTX> HashStable for WithStableHash { +impl, CTX> HashStable for WithCachedTypeInfo { 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 e83106b1ee5..3f3d92d68e3 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -88,8 +88,8 @@ macro_rules! arena_types { [] hir_id_set: rustc_hir::HirIdSet, // Interned types - [] tys: rustc_data_structures::intern::WithStableHash>, - [] predicates: rustc_data_structures::intern::WithStableHash>, + [] tys: rustc_data_structures::intern::WithCachedTypeInfo>, + [] predicates: rustc_data_structures::intern::WithCachedTypeInfo>, [] 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 a1acca3097d..3af3444b86c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -27,7 +27,7 @@ use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubst use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::intern::{Interned, WithStableHash}; +use rustc_data_structures::intern::{Interned, WithCachedTypeInfo}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; @@ -136,13 +136,13 @@ pub struct CtxtInterners<'tcx> { // Specifically use a speedy hash algorithm for these hash sets, since // they're accessed quite often. - type_: InternedSet<'tcx, WithStableHash>>, + type_: InternedSet<'tcx, WithCachedTypeInfo>>, const_lists: InternedSet<'tcx, List>>, substs: InternedSet<'tcx, InternalSubsts<'tcx>>, canonical_var_infos: InternedSet<'tcx, List>>, region: InternedSet<'tcx, RegionKind<'tcx>>, poly_existential_predicates: InternedSet<'tcx, List>>, - predicate: InternedSet<'tcx, WithStableHash>>, + predicate: InternedSet<'tcx, WithCachedTypeInfo>>, predicates: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, @@ -200,7 +200,7 @@ impl<'tcx> CtxtInterners<'tcx> { }; InternedInSet( - self.arena.alloc(WithStableHash { internee: ty_struct, stable_hash }), + self.arena.alloc(WithCachedTypeInfo { internee: ty_struct, stable_hash }), ) }) .0, @@ -253,7 +253,7 @@ impl<'tcx> CtxtInterners<'tcx> { InternedInSet( self.arena - .alloc(WithStableHash { internee: predicate_struct, stable_hash }), + .alloc(WithCachedTypeInfo { internee: predicate_struct, stable_hash }), ) }) .0, @@ -2167,23 +2167,23 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> { } #[allow(rustc::usage_of_ty_tykind)] -impl<'tcx> Borrow> for InternedInSet<'tcx, WithStableHash>> { +impl<'tcx> Borrow> for InternedInSet<'tcx, WithCachedTypeInfo>> { fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { &self.0.kind } } -impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash>> { - fn eq(&self, other: &InternedInSet<'tcx, WithStableHash>>) -> bool { +impl<'tcx> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo>> { + fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>>) -> 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, WithStableHash>> {} +impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>> {} -impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash>> { +impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { fn hash(&self, s: &mut H) { // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. self.0.kind.hash(s) @@ -2191,24 +2191,24 @@ impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash>> { } impl<'tcx> Borrow>> - for InternedInSet<'tcx, WithStableHash>> + for InternedInSet<'tcx, WithCachedTypeInfo>> { fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> { &self.0.kind } } -impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash>> { - fn eq(&self, other: &InternedInSet<'tcx, WithStableHash>>) -> bool { +impl<'tcx> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo>> { + fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>>) -> 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, WithStableHash>> {} +impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>> {} -impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash>> { +impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { 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 dd4ab3e8d30..d3cbd2e03cf 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -32,7 +32,7 @@ use rustc_ast::node_id::NodeMap; use rustc_attr as attr; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_data_structures::intern::{Interned, WithStableHash}; +use rustc_data_structures::intern::{Interned, WithCachedTypeInfo}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; @@ -495,19 +495,20 @@ pub(crate) struct TyS<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_diagnostic_item = "Ty"] #[rustc_pass_by_value] -pub struct Ty<'tcx>(Interned<'tcx, WithStableHash>>); +pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); impl<'tcx> TyCtxt<'tcx> { /// A "bool" type used in rustc_mir_transform unit tests when we /// have not spun up a TyCtxt. - pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> = Ty(Interned::new_unchecked(&WithStableHash { - internee: TyS { - kind: ty::Bool, - flags: TypeFlags::empty(), - outer_exclusive_binder: DebruijnIndex::from_usize(0), - }, - stable_hash: Fingerprint::ZERO, - })); + pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> = + Ty(Interned::new_unchecked(&WithCachedTypeInfo { + internee: TyS { + kind: ty::Bool, + flags: TypeFlags::empty(), + outer_exclusive_binder: DebruijnIndex::from_usize(0), + }, + stable_hash: Fingerprint::ZERO, + })); } impl<'a, 'tcx> HashStable> for TyS<'tcx> { @@ -550,7 +551,7 @@ pub(crate) struct PredicateS<'tcx> { /// Use this rather than `PredicateS`, whenever possible. #[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] -pub struct Predicate<'tcx>(Interned<'tcx, WithStableHash>>); +pub struct Predicate<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); impl<'tcx> Predicate<'tcx> { /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. @@ -1028,7 +1029,7 @@ impl<'tcx> Term<'tcx> { unsafe { match ptr & TAG_MASK { TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithStableHash>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), @@ -1072,7 +1073,7 @@ impl<'tcx> TermKind<'tcx> { TermKind::Ty(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 WithStableHash> as usize) + (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) } TermKind::Const(ct) => { // Ensure we can use the tag bits. @@ -2694,6 +2695,6 @@ mod size_asserts { // tidy-alphabetical-start static_assert_size!(PredicateS<'_>, 48); static_assert_size!(TyS<'_>, 40); - static_assert_size!(WithStableHash>, 56); + static_assert_size!(WithCachedTypeInfo>, 56); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 141c8354c18..f69035f619f 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -6,7 +6,7 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; use crate::ty::visit::{TypeVisitable, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; -use rustc_data_structures::intern::{Interned, WithStableHash}; +use rustc_data_structures::intern::{Interned, WithCachedTypeInfo}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{self, Decodable, Encodable}; @@ -84,7 +84,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 WithStableHash> as usize) + (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) } GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. @@ -162,7 +162,7 @@ impl<'tcx> GenericArg<'tcx> { &*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>), ))), TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithStableHash>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), From 87a04f51ba4ccf9f6b44897713edaa7c68dc580a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 25 Nov 2022 16:38:16 +0000 Subject: [PATCH 2/6] move WithCachedTypeInfo to rustc_type_ir --- compiler/rustc_data_structures/src/intern.rs | 83 ------------------ compiler/rustc_middle/src/arena.rs | 4 +- compiler/rustc_middle/src/ty/context.rs | 3 +- compiler/rustc_middle/src/ty/mod.rs | 3 +- compiler/rustc_middle/src/ty/subst.rs | 3 +- compiler/rustc_type_ir/src/lib.rs | 2 + compiler/rustc_type_ir/src/ty_info.rs | 91 ++++++++++++++++++++ 7 files changed, 101 insertions(+), 88 deletions(-) create mode 100644 compiler/rustc_type_ir/src/ty_info.rs diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs index 9985aeaab57..7a320b10b60 100644 --- a/compiler/rustc_data_structures/src/intern.rs +++ b/compiler/rustc_data_structures/src/intern.rs @@ -4,8 +4,6 @@ use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::ptr; -use crate::fingerprint::Fingerprint; - mod private { #[derive(Clone, Copy, Debug)] pub struct PrivateZst; @@ -110,86 +108,5 @@ where } } -/// 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 WithCachedTypeInfo { - pub internee: T, - pub stable_hash: Fingerprint, -} - -impl PartialEq for WithCachedTypeInfo { - #[inline] - fn eq(&self, other: &Self) -> bool { - self.internee.eq(&other.internee) - } -} - -impl Eq for WithCachedTypeInfo {} - -impl PartialOrd for WithCachedTypeInfo { - fn partial_cmp(&self, other: &WithCachedTypeInfo) -> Option { - Some(self.internee.cmp(&other.internee)) - } -} - -impl Ord for WithCachedTypeInfo { - fn cmp(&self, other: &WithCachedTypeInfo) -> Ordering { - self.internee.cmp(&other.internee) - } -} - -impl Deref for WithCachedTypeInfo { - type Target = T; - - #[inline] - fn deref(&self) -> &T { - &self.internee - } -} - -impl Hash for WithCachedTypeInfo { - #[inline] - fn hash(&self, s: &mut H) { - if self.stable_hash != Fingerprint::ZERO { - self.stable_hash.hash(s) - } else { - self.internee.hash(s) - } - } -} - -impl, CTX> HashStable for WithCachedTypeInfo { - 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. - // We don't cache stable hashes in non-incremental mode, because they are used - // so rarely that the performance actually suffers. - - // We need to build the hash as if we cached it and then hash that hash, as - // otherwise the hashes will differ between cached and non-cached mode. - let stable_hash: Fingerprint = { - let mut hasher = StableHasher::new(); - self.internee.hash_stable(hcx, &mut hasher); - hasher.finish() - }; - if cfg!(debug_assertions) && self.stable_hash != Fingerprint::ZERO { - assert_eq!( - stable_hash, self.stable_hash, - "cached stable hash does not match freshly computed stable hash" - ); - } - stable_hash.hash_stable(hcx, hasher); - } else { - self.stable_hash.hash_stable(hcx, hasher); - } - } -} - #[cfg(test)] mod tests; diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 3f3d92d68e3..2cbc381a11a 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -88,8 +88,8 @@ macro_rules! arena_types { [] hir_id_set: rustc_hir::HirIdSet, // Interned types - [] tys: rustc_data_structures::intern::WithCachedTypeInfo>, - [] predicates: rustc_data_structures::intern::WithCachedTypeInfo>, + [] tys: rustc_type_ir::WithCachedTypeInfo>, + [] predicates: rustc_type_ir::WithCachedTypeInfo>, [] 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 3af3444b86c..e1834f1f57a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -27,7 +27,7 @@ use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubst use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::intern::{Interned, WithCachedTypeInfo}; +use rustc_data_structures::intern::Interned; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; @@ -67,6 +67,7 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; use rustc_type_ir::sty::TyKind::*; +use rustc_type_ir::WithCachedTypeInfo; use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlags}; use std::any::Any; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d3cbd2e03cf..c56e1b6e5a0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -32,7 +32,7 @@ use rustc_ast::node_id::NodeMap; use rustc_attr as attr; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_data_structures::intern::{Interned, WithCachedTypeInfo}; +use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; @@ -50,6 +50,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ExpnId, Span}; use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx}; pub use rustc_target::abi::{ReprFlags, ReprOptions}; +use rustc_type_ir::WithCachedTypeInfo; pub use subst::*; pub use vtable::*; diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index f69035f619f..13fab0068d6 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -6,10 +6,11 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; use crate::ty::visit::{TypeVisitable, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; -use rustc_data_structures::intern::{Interned, WithCachedTypeInfo}; +use rustc_data_structures::intern::Interned; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{self, Decodable, Encodable}; +use rustc_type_ir::WithCachedTypeInfo; use smallvec::SmallVec; use core::intrinsics; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 581993ba7d8..e3f7a1bd033 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -19,9 +19,11 @@ use std::mem::discriminant; pub mod codec; pub mod sty; +pub mod ty_info; pub use codec::*; pub use sty::*; +pub use ty_info::*; /// Needed so we can use #[derive(HashStable_Generic)] pub trait HashStableContext {} diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs new file mode 100644 index 00000000000..815237a06c0 --- /dev/null +++ b/compiler/rustc_type_ir/src/ty_info.rs @@ -0,0 +1,91 @@ +use std::{ + cmp::Ordering, + hash::{Hash, Hasher}, + ops::Deref, +}; + +use rustc_data_structures::{ + fingerprint::Fingerprint, + stable_hasher::{HashStable, StableHasher}, +}; + +/// 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 WithCachedTypeInfo { + pub internee: T, + pub stable_hash: Fingerprint, +} + +impl PartialEq for WithCachedTypeInfo { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.internee.eq(&other.internee) + } +} + +impl Eq for WithCachedTypeInfo {} + +impl PartialOrd for WithCachedTypeInfo { + fn partial_cmp(&self, other: &WithCachedTypeInfo) -> Option { + Some(self.internee.cmp(&other.internee)) + } +} + +impl Ord for WithCachedTypeInfo { + fn cmp(&self, other: &WithCachedTypeInfo) -> Ordering { + self.internee.cmp(&other.internee) + } +} + +impl Deref for WithCachedTypeInfo { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + &self.internee + } +} + +impl Hash for WithCachedTypeInfo { + #[inline] + fn hash(&self, s: &mut H) { + if self.stable_hash != Fingerprint::ZERO { + self.stable_hash.hash(s) + } else { + self.internee.hash(s) + } + } +} + +impl, CTX> HashStable for WithCachedTypeInfo { + 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. + // We don't cache stable hashes in non-incremental mode, because they are used + // so rarely that the performance actually suffers. + + // We need to build the hash as if we cached it and then hash that hash, as + // otherwise the hashes will differ between cached and non-cached mode. + let stable_hash: Fingerprint = { + let mut hasher = StableHasher::new(); + self.internee.hash_stable(hcx, &mut hasher); + hasher.finish() + }; + if cfg!(debug_assertions) && self.stable_hash != Fingerprint::ZERO { + assert_eq!( + stable_hash, self.stable_hash, + "cached stable hash does not match freshly computed stable hash" + ); + } + stable_hash.hash_stable(hcx, hasher); + } else { + self.stable_hash.hash_stable(hcx, hasher); + } + } +} From 147b854dede7b0dda933e24f6ee6c8dd30323a7e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 25 Nov 2022 16:55:25 +0000 Subject: [PATCH 3/6] Remove TyS --- compiler/rustc_middle/src/arena.rs | 4 +- compiler/rustc_middle/src/ty/context.rs | 35 +++++------ compiler/rustc_middle/src/ty/mod.rs | 82 +++---------------------- compiler/rustc_middle/src/ty/sty.rs | 2 +- compiler/rustc_middle/src/ty/subst.rs | 4 +- compiler/rustc_type_ir/src/ty_info.rs | 35 ++++++++++- 6 files changed, 65 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 2cbc381a11a..3a0ddae1c63 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -1,3 +1,5 @@ +#![allow(rustc::usage_of_ty_tykind)] + /// This higher-order macro declares a list of types which can be allocated by `Arena`. /// /// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]` where `T` is the type @@ -88,7 +90,7 @@ macro_rules! arena_types { [] hir_id_set: rustc_hir::HirIdSet, // Interned types - [] tys: rustc_type_ir::WithCachedTypeInfo>, + [] tys: rustc_type_ir::WithCachedTypeInfo>, [] predicates: rustc_type_ir::WithCachedTypeInfo>, [] 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 e1834f1f57a..f798c0a4e22 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1,5 +1,7 @@ //! Type context book-keeping. +#![allow(rustc::usage_of_ty_tykind)] + use crate::arena::Arena; use crate::dep_graph::{DepGraph, DepKindStruct}; use crate::hir::place::Place as HirPlace; @@ -20,7 +22,7 @@ use crate::ty::{ ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid, GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy, - Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, + Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility, }; use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts}; @@ -137,7 +139,7 @@ pub struct CtxtInterners<'tcx> { // Specifically use a speedy hash algorithm for these hash sets, since // they're accessed quite often. - type_: InternedSet<'tcx, WithCachedTypeInfo>>, + type_: InternedSet<'tcx, WithCachedTypeInfo>>, const_lists: InternedSet<'tcx, List>>, substs: InternedSet<'tcx, InternalSubsts<'tcx>>, canonical_var_infos: InternedSet<'tcx, List>>, @@ -194,15 +196,12 @@ impl<'tcx> CtxtInterners<'tcx> { let stable_hash = self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); - let ty_struct = TyS { - kind, + InternedInSet(self.arena.alloc(WithCachedTypeInfo { + internee: kind, + stable_hash, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, - }; - - InternedInSet( - self.arena.alloc(WithCachedTypeInfo { internee: ty_struct, stable_hash }), - ) + })) }) .0, )) @@ -2058,7 +2057,7 @@ macro_rules! sty_debug_print { let shards = tcx.interners.type_.lock_shards(); let types = shards.iter().flat_map(|shard| shard.keys()); for &InternedInSet(t) in types { - let variant = match t.kind { + let variant = match t.internee { ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | ty::Float(..) | ty::Str | ty::Never => continue, ty::Error(_) => /* unimportant */ continue, @@ -2168,26 +2167,26 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> { } #[allow(rustc::usage_of_ty_tykind)] -impl<'tcx> Borrow> for InternedInSet<'tcx, WithCachedTypeInfo>> { +impl<'tcx> Borrow> for InternedInSet<'tcx, WithCachedTypeInfo>> { fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { - &self.0.kind + &self.0.internee } } -impl<'tcx> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo>> { - fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>>) -> bool { +impl<'tcx> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo>> { + fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>>) -> bool { // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals // `x == y`. - self.0.kind == other.0.kind + self.0.internee == other.0.internee } } -impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>> {} +impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>> {} -impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { +impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { fn hash(&self, s: &mut H) { // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. - self.0.kind.hash(s) + self.0.internee.hash(s) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c56e1b6e5a0..667b55088cc 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -9,6 +9,8 @@ //! //! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html +#![allow(rustc::usage_of_ty_tykind)] + pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; pub use self::AssocItemContainer::*; @@ -446,89 +448,24 @@ pub struct CReaderCacheKey { pub pos: usize, } -/// Represents a type. -/// -/// IMPORTANT: -/// - This is a very "dumb" struct (with no derives and no `impls`). -/// - Values of this type are always interned and thus unique, and are stored -/// as an `Interned`. -/// - `Ty` (which contains a reference to a `Interned`) or `Interned` -/// should be used everywhere instead of `TyS`. In particular, `Ty` has most -/// of the relevant methods. -#[derive(PartialEq, Eq, PartialOrd, Ord)] -#[allow(rustc::usage_of_ty_tykind)] -pub(crate) struct TyS<'tcx> { - /// This field shouldn't be used directly and may be removed in the future. - /// Use `Ty::kind()` instead. - kind: TyKind<'tcx>, - - /// This field provides fast access to information that is also contained - /// in `kind`. - /// - /// This field shouldn't be used directly and may be removed in the future. - /// Use `Ty::flags()` instead. - flags: TypeFlags, - - /// This field provides fast access to information that is also contained - /// in `kind`. - /// - /// This is a kind of confusing thing: it stores the smallest - /// binder such that - /// - /// (a) the binder itself captures nothing but - /// (b) all the late-bound things within the type are captured - /// by some sub-binder. - /// - /// So, for a type without any late-bound things, like `u32`, this - /// will be *innermost*, because that is the innermost binder that - /// captures nothing. But for a type `&'D u32`, where `'D` is a - /// late-bound region with De Bruijn index `D`, this would be `D + 1` - /// -- the binder itself does not capture `D`, but `D` is captured - /// by an inner binder. - /// - /// We call this concept an "exclusive" binder `D` because all - /// De Bruijn indices within the type are contained within `0..D` - /// (exclusive). - outer_exclusive_binder: ty::DebruijnIndex, -} - /// 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, WithCachedTypeInfo>>); +pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); impl<'tcx> TyCtxt<'tcx> { /// A "bool" type used in rustc_mir_transform unit tests when we /// have not spun up a TyCtxt. pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> = Ty(Interned::new_unchecked(&WithCachedTypeInfo { - internee: TyS { - kind: ty::Bool, - flags: TypeFlags::empty(), - outer_exclusive_binder: DebruijnIndex::from_usize(0), - }, + internee: ty::Bool, stable_hash: Fingerprint::ZERO, + flags: TypeFlags::empty(), + outer_exclusive_binder: DebruijnIndex::from_usize(0), })); } -impl<'a, 'tcx> HashStable> for TyS<'tcx> { - #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let TyS { - kind, - - // The other fields just provide fast access to information that is - // also contained in `kind`, so no need to hash them. - flags: _, - - outer_exclusive_binder: _, - } = self; - - kind.hash_stable(hcx, hasher) - } -} - impl ty::EarlyBoundRegion { /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). @@ -1030,7 +967,7 @@ impl<'tcx> Term<'tcx> { unsafe { match ptr & TAG_MASK { TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), @@ -1074,7 +1011,7 @@ impl<'tcx> TermKind<'tcx> { TermKind::Ty(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 WithCachedTypeInfo> as usize) + (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) } TermKind::Const(ct) => { // Ensure we can use the tag bits. @@ -2695,7 +2632,6 @@ mod size_asserts { use rustc_data_structures::static_assert_size; // tidy-alphabetical-start static_assert_size!(PredicateS<'_>, 48); - static_assert_size!(TyS<'_>, 40); - static_assert_size!(WithCachedTypeInfo>, 56); + static_assert_size!(WithCachedTypeInfo>, 56); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 5984686044b..a90f4f91377 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1602,7 +1602,7 @@ impl<'tcx> Region<'tcx> { impl<'tcx> Ty<'tcx> { #[inline(always)] pub fn kind(self) -> &'tcx TyKind<'tcx> { - &self.0.0.kind + &self.0.0 } #[inline(always)] diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 13fab0068d6..89901d1575a 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -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 WithCachedTypeInfo> as usize) + (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) } GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. @@ -163,7 +163,7 @@ impl<'tcx> GenericArg<'tcx> { &*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>), ))), TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs index 815237a06c0..4e5d424886a 100644 --- a/compiler/rustc_type_ir/src/ty_info.rs +++ b/compiler/rustc_type_ir/src/ty_info.rs @@ -9,9 +9,11 @@ use rustc_data_structures::{ stable_hasher::{HashStable, StableHasher}, }; +use crate::{DebruijnIndex, TypeFlags}; + /// 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. +/// cache the stable hash, type flags and debruijn index on creation and +/// not recompute it whenever the information is needed. /// 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 @@ -20,6 +22,35 @@ use rustc_data_structures::{ pub struct WithCachedTypeInfo { pub internee: T, pub stable_hash: Fingerprint, + + /// This field provides fast access to information that is also contained + /// in `kind`. + /// + /// This field shouldn't be used directly and may be removed in the future. + /// Use `Ty::flags()` instead. + pub flags: TypeFlags, + + /// This field provides fast access to information that is also contained + /// in `kind`. + /// + /// This is a kind of confusing thing: it stores the smallest + /// binder such that + /// + /// (a) the binder itself captures nothing but + /// (b) all the late-bound things within the type are captured + /// by some sub-binder. + /// + /// So, for a type without any late-bound things, like `u32`, this + /// will be *innermost*, because that is the innermost binder that + /// captures nothing. But for a type `&'D u32`, where `'D` is a + /// late-bound region with De Bruijn index `D`, this would be `D + 1` + /// -- the binder itself does not capture `D`, but `D` is captured + /// by an inner binder. + /// + /// We call this concept an "exclusive" binder `D` because all + /// De Bruijn indices within the type are contained within `0..D` + /// (exclusive). + pub outer_exclusive_binder: DebruijnIndex, } impl PartialEq for WithCachedTypeInfo { From 46ba1545b89020486fb9da460e9f3b7b60e83c40 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 28 Nov 2022 14:23:49 +0000 Subject: [PATCH 4/6] Update documentation --- compiler/rustc_lint/src/pass_by_value.rs | 2 +- compiler/rustc_middle/src/mir/interpret/allocation.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index cf1d82f4c06..0fa81b7e4e0 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -10,7 +10,7 @@ declare_tool_lint! { /// The `rustc_pass_by_value` lint marks a type with `#[rustc_pass_by_value]` requiring it to /// always be passed by value. This is usually used for types that are thin wrappers around /// references, so there is no benefit to an extra layer of indirection. (Example: `Ty` which - /// is a reference to an `Interned`) + /// is a reference to an `Interned`) pub rustc::PASS_BY_VALUE, Warn, "pass by reference of a type flagged as `#[rustc_pass_by_value]`", diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 5f911d5884a..221105ac48f 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -103,7 +103,7 @@ impl hash::Hash for Allocation { /// Interned types generally have an `Outer` type and an `Inner` type, where /// `Outer` is a newtype around `Interned`, and all the operations are /// done on `Outer`, because all occurrences are interned. E.g. `Ty` is an -/// outer type and `TyS` is its inner type. +/// outer type and `TyKind` is its inner type. /// /// Here things are different because only const allocations are interned. This /// means that both the inner type (`Allocation`) and the outer type diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 667b55088cc..756c0c583ad 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -448,7 +448,7 @@ pub struct CReaderCacheKey { pub pos: usize, } -/// Use this rather than `TyS`, whenever possible. +/// Use this rather than `TyKind`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_diagnostic_item = "Ty"] #[rustc_pass_by_value] @@ -476,13 +476,13 @@ impl ty::EarlyBoundRegion { /// Represents a predicate. /// -/// See comments on `TyS`, which apply here too (albeit for -/// `PredicateS`/`Predicate` rather than `TyS`/`Ty`). +/// See comments on `WithCachedTypeInfo`, which apply here too (albeit for +/// `PredicateS`/`Predicate` rather than `TyKind`/`Ty`). #[derive(Debug)] pub(crate) struct PredicateS<'tcx> { kind: Binder<'tcx, PredicateKind<'tcx>>, flags: TypeFlags, - /// See the comment for the corresponding field of [TyS]. + /// See the comment for the corresponding field of [WithCachedTypeInfo]. outer_exclusive_binder: ty::DebruijnIndex, } From 907ef227ef22bed182100641564a223a23dcba62 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 30 Nov 2022 14:47:40 +0000 Subject: [PATCH 5/6] Remove PredicateS type --- compiler/rustc_middle/src/arena.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 41 +++++++++++++------------ compiler/rustc_middle/src/ty/mod.rs | 37 ++++------------------ 3 files changed, 28 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 3a0ddae1c63..f8063dd238b 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -91,7 +91,7 @@ macro_rules! arena_types { // Interned types [] tys: rustc_type_ir::WithCachedTypeInfo>, - [] predicates: rustc_type_ir::WithCachedTypeInfo>, + [] predicates: rustc_type_ir::WithCachedTypeInfo>, [] 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 f798c0a4e22..850b25473d6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -21,9 +21,9 @@ use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid, GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, - PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy, - Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, - UintTy, Visibility, + PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, ProjectionTy, Region, + RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, + Visibility, }; use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts}; use rustc_ast as ast; @@ -145,7 +145,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, WithCachedTypeInfo>>, + predicate: InternedSet<'tcx, WithCachedTypeInfo>>>, predicates: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, @@ -245,16 +245,12 @@ impl<'tcx> CtxtInterners<'tcx> { let stable_hash = self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); - let predicate_struct = PredicateS { - kind, + InternedInSet(self.arena.alloc(WithCachedTypeInfo { + internee: kind, + stable_hash, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, - }; - - InternedInSet( - self.arena - .alloc(WithCachedTypeInfo { internee: predicate_struct, stable_hash }), - ) + })) }) .0, )) @@ -2191,27 +2187,32 @@ impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { } impl<'tcx> Borrow>> - for InternedInSet<'tcx, WithCachedTypeInfo>> + for InternedInSet<'tcx, WithCachedTypeInfo>>> { fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> { - &self.0.kind + &self.0.internee } } -impl<'tcx> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo>> { - fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>>) -> bool { +impl<'tcx> PartialEq + for InternedInSet<'tcx, WithCachedTypeInfo>>> +{ + fn eq( + &self, + other: &InternedInSet<'tcx, WithCachedTypeInfo>>>, + ) -> bool { // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals // `x == y`. - self.0.kind == other.0.kind + self.0.internee == other.0.internee } } -impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>> {} +impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>>> {} -impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { +impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>>> { fn hash(&self, s: &mut H) { // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. - self.0.kind.hash(s) + self.0.internee.hash(s) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 756c0c583ad..4b4b5126719 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -474,28 +474,18 @@ impl ty::EarlyBoundRegion { } } -/// Represents a predicate. -/// -/// See comments on `WithCachedTypeInfo`, which apply here too (albeit for -/// `PredicateS`/`Predicate` rather than `TyKind`/`Ty`). -#[derive(Debug)] -pub(crate) struct PredicateS<'tcx> { - kind: Binder<'tcx, PredicateKind<'tcx>>, - flags: TypeFlags, - /// See the comment for the corresponding field of [WithCachedTypeInfo]. - outer_exclusive_binder: ty::DebruijnIndex, -} - -/// Use this rather than `PredicateS`, whenever possible. +/// Use this rather than `PredicateKind`, whenever possible. #[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] -pub struct Predicate<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); +pub struct Predicate<'tcx>( + Interned<'tcx, WithCachedTypeInfo>>>, +); impl<'tcx> Predicate<'tcx> { /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. #[inline] pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { - self.0.kind + self.0.internee } #[inline(always)] @@ -570,21 +560,6 @@ impl<'tcx> Predicate<'tcx> { } } -impl<'a, 'tcx> HashStable> for PredicateS<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let PredicateS { - ref kind, - - // The other fields just provide fast access to information that is - // also contained in `kind`, so no need to hash them. - flags: _, - outer_exclusive_binder: _, - } = self; - - kind.hash_stable(hcx, hasher); - } -} - impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) @@ -2631,7 +2606,7 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // tidy-alphabetical-start - static_assert_size!(PredicateS<'_>, 48); + static_assert_size!(PredicateKind<'_>, 32); static_assert_size!(WithCachedTypeInfo>, 56); // tidy-alphabetical-end } From 14a9cf2ba2178f6f776ca22bd45a83bdf27b39cd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 30 Nov 2022 14:52:05 +0000 Subject: [PATCH 6/6] Generalize some InternedInSet impls --- compiler/rustc_middle/src/ty/context.rs | 42 ++++--------------------- 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 850b25473d6..89d4ad31d1e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2163,53 +2163,23 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> { } #[allow(rustc::usage_of_ty_tykind)] -impl<'tcx> Borrow> for InternedInSet<'tcx, WithCachedTypeInfo>> { - fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { +impl<'tcx, T> Borrow for InternedInSet<'tcx, WithCachedTypeInfo> { + fn borrow<'a>(&'a self) -> &'a T { &self.0.internee } } -impl<'tcx> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo>> { - fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>>) -> bool { +impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo> { + fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>) -> bool { // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals // `x == y`. self.0.internee == other.0.internee } } -impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>> {} +impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, WithCachedTypeInfo> {} -impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { - fn hash(&self, s: &mut H) { - // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. - self.0.internee.hash(s) - } -} - -impl<'tcx> Borrow>> - for InternedInSet<'tcx, WithCachedTypeInfo>>> -{ - fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> { - &self.0.internee - } -} - -impl<'tcx> PartialEq - for InternedInSet<'tcx, WithCachedTypeInfo>>> -{ - fn eq( - &self, - other: &InternedInSet<'tcx, WithCachedTypeInfo>>>, - ) -> bool { - // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals - // `x == y`. - self.0.internee == other.0.internee - } -} - -impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>>> {} - -impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>>> { +impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo> { fn hash(&self, s: &mut H) { // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. self.0.internee.hash(s)