Skip to content

Commit 00c24dd

Browse files
committed
Move stable hash from TyS into a datastructure that can be shared with other interned types.
1 parent df20355 commit 00c24dd

File tree

8 files changed

+140
-64
lines changed

8 files changed

+140
-64
lines changed

compiler/rustc_data_structures/src/intern.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use std::hash::{Hash, Hasher};
44
use std::ops::Deref;
55
use std::ptr;
66

7+
use crate::fingerprint::Fingerprint;
8+
79
mod private {
810
#[derive(Clone, Copy, Debug)]
911
pub struct PrivateZst;
@@ -108,5 +110,76 @@ where
108110
}
109111
}
110112

113+
/// A helper trait so that `Interned` things can cache stable hashes reproducibly.
114+
pub trait InternedHashingContext {
115+
fn with_def_path_and_no_spans(&mut self, f: impl FnOnce(&mut Self));
116+
}
117+
118+
#[derive(Copy, Clone)]
119+
pub struct InTy<T> {
120+
pub internee: T,
121+
pub stable_hash: Fingerprint,
122+
}
123+
124+
impl<T: PartialEq> PartialEq for InTy<T> {
125+
#[inline]
126+
fn eq(&self, other: &Self) -> bool {
127+
self.internee.eq(&other.internee)
128+
}
129+
}
130+
131+
impl<T: Eq> Eq for InTy<T> {}
132+
133+
impl<T: Ord> PartialOrd for InTy<T> {
134+
fn partial_cmp(&self, other: &InTy<T>) -> Option<Ordering> {
135+
Some(self.internee.cmp(&other.internee))
136+
}
137+
}
138+
139+
impl<T: Ord> Ord for InTy<T> {
140+
fn cmp(&self, other: &InTy<T>) -> Ordering {
141+
self.internee.cmp(&other.internee)
142+
}
143+
}
144+
145+
impl<T> Deref for InTy<T> {
146+
type Target = T;
147+
148+
#[inline]
149+
fn deref(&self) -> &T {
150+
&self.internee
151+
}
152+
}
153+
154+
impl<T: Hash> Hash for InTy<T> {
155+
#[inline]
156+
fn hash<H: Hasher>(&self, s: &mut H) {
157+
self.internee.hash(s)
158+
}
159+
}
160+
161+
impl<T: HashStable<CTX>, CTX: InternedHashingContext> HashStable<CTX> for InTy<T> {
162+
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
163+
let stable_hash = self.stable_hash;
164+
165+
if stable_hash == Fingerprint::ZERO {
166+
// No cached hash available. This can only mean that incremental is disabled.
167+
// We don't cache stable hashes in non-incremental mode, because they are used
168+
// so rarely that the performance actually suffers.
169+
170+
// We need to build the hash as if we cached it and then hash that hash, as
171+
// otherwise the hashes will differ between cached and non-cached mode.
172+
let stable_hash: Fingerprint = {
173+
let mut hasher = StableHasher::new();
174+
hcx.with_def_path_and_no_spans(|hcx| self.internee.hash_stable(hcx, &mut hasher));
175+
hasher.finish()
176+
};
177+
stable_hash.hash_stable(hcx, hasher);
178+
} else {
179+
stable_hash.hash_stable(hcx, hasher);
180+
}
181+
}
182+
}
183+
111184
#[cfg(test)]
112185
mod tests;

compiler/rustc_middle/src/arena.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ macro_rules! arena_types {
8787
[] hir_id_set: rustc_hir::HirIdSet,
8888

8989
// Interned types
90-
[] tys: rustc_middle::ty::TyS<'tcx>,
90+
[] tys: rustc_data_structures::intern::InTy<rustc_middle::ty::TyS<'tcx>>,
9191
[] predicates: rustc_middle::ty::PredicateS<'tcx>,
9292
[] consts: rustc_middle::ty::ConstS<'tcx>,
9393

compiler/rustc_middle/src/ty/context.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::ty::{
2626
use rustc_ast as ast;
2727
use rustc_data_structures::fingerprint::Fingerprint;
2828
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
29-
use rustc_data_structures::intern::Interned;
29+
use rustc_data_structures::intern::{InTy, Interned};
3030
use rustc_data_structures::memmap::Mmap;
3131
use rustc_data_structures::profiling::SelfProfilerRef;
3232
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
@@ -105,7 +105,7 @@ pub struct CtxtInterners<'tcx> {
105105

106106
// Specifically use a speedy hash algorithm for these hash sets, since
107107
// they're accessed quite often.
108-
type_: InternedSet<'tcx, TyS<'tcx>>,
108+
type_: InternedSet<'tcx, InTy<TyS<'tcx>>>,
109109
substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
110110
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
111111
region: InternedSet<'tcx, RegionKind>,
@@ -178,10 +178,9 @@ impl<'tcx> CtxtInterners<'tcx> {
178178
kind,
179179
flags: flags.flags,
180180
outer_exclusive_binder: flags.outer_exclusive_binder,
181-
stable_hash,
182181
};
183182

184-
InternedInSet(self.arena.alloc(ty_struct))
183+
InternedInSet(self.arena.alloc(InTy { internee: ty_struct, stable_hash }))
185184
})
186185
.0,
187186
))
@@ -2048,23 +2047,23 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> {
20482047
}
20492048

20502049
#[allow(rustc::usage_of_ty_tykind)]
2051-
impl<'tcx> Borrow<TyKind<'tcx>> for InternedInSet<'tcx, TyS<'tcx>> {
2050+
impl<'tcx> Borrow<TyKind<'tcx>> for InternedInSet<'tcx, InTy<TyS<'tcx>>> {
20522051
fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> {
20532052
&self.0.kind
20542053
}
20552054
}
20562055

2057-
impl<'tcx> PartialEq for InternedInSet<'tcx, TyS<'tcx>> {
2058-
fn eq(&self, other: &InternedInSet<'tcx, TyS<'tcx>>) -> bool {
2056+
impl<'tcx> PartialEq for InternedInSet<'tcx, InTy<TyS<'tcx>>> {
2057+
fn eq(&self, other: &InternedInSet<'tcx, InTy<TyS<'tcx>>>) -> bool {
20592058
// The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
20602059
// `x == y`.
20612060
self.0.kind == other.0.kind
20622061
}
20632062
}
20642063

2065-
impl<'tcx> Eq for InternedInSet<'tcx, TyS<'tcx>> {}
2064+
impl<'tcx> Eq for InternedInSet<'tcx, InTy<TyS<'tcx>>> {}
20662065

2067-
impl<'tcx> Hash for InternedInSet<'tcx, TyS<'tcx>> {
2066+
impl<'tcx> Hash for InternedInSet<'tcx, InTy<TyS<'tcx>>> {
20682067
fn hash<H: Hasher>(&self, s: &mut H) {
20692068
// The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
20702069
self.0.kind.hash(s)

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ use crate::ty::util::Discr;
3131
use rustc_ast as ast;
3232
use rustc_attr as attr;
3333
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
34-
use rustc_data_structures::intern::Interned;
35-
use rustc_data_structures::stable_hasher::{HashStable, NodeIdHashingMode, StableHasher};
34+
use rustc_data_structures::intern::{InTy, Interned};
35+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
3636
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
3737
use rustc_hir as hir;
3838
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@@ -433,32 +433,28 @@ crate struct TyS<'tcx> {
433433
/// De Bruijn indices within the type are contained within `0..D`
434434
/// (exclusive).
435435
outer_exclusive_binder: ty::DebruijnIndex,
436-
437-
/// The stable hash of the type. This way hashing of types will not have to work
438-
/// on the address of the type anymore, but can instead just read this field
439-
stable_hash: Fingerprint,
440436
}
441437

442438
// `TyS` is used a lot. Make sure it doesn't unintentionally get bigger.
443439
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
444-
static_assert_size!(TyS<'_>, 56);
440+
static_assert_size!(TyS<'_>, 40);
445441

446442
/// Use this rather than `TyS`, whenever possible.
447-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
443+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
448444
#[rustc_diagnostic_item = "Ty"]
449445
#[rustc_pass_by_value]
450-
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
446+
pub struct Ty<'tcx>(Interned<'tcx, InTy<TyS<'tcx>>>);
451447

452448
// Statics only used for internal testing.
453-
pub static BOOL_TY: Ty<'static> = Ty(Interned::new_unchecked(&BOOL_TYS));
454-
static BOOL_TYS: TyS<'static> = TyS {
449+
pub static BOOL_TY: Ty<'static> =
450+
Ty(Interned::new_unchecked(&InTy { internee: BOOL_TYS, stable_hash: Fingerprint::ZERO }));
451+
const BOOL_TYS: TyS<'static> = TyS {
455452
kind: ty::Bool,
456453
flags: TypeFlags::empty(),
457454
outer_exclusive_binder: DebruijnIndex::from_usize(0),
458-
stable_hash: Fingerprint::ZERO,
459455
};
460456

461-
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Ty<'tcx> {
457+
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
462458
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
463459
let TyS {
464460
kind,
@@ -468,28 +464,9 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Ty<'tcx> {
468464
flags: _,
469465

470466
outer_exclusive_binder: _,
467+
} = self;
471468

472-
stable_hash,
473-
} = self.0.0;
474-
475-
if *stable_hash == Fingerprint::ZERO {
476-
// No cached hash available. This can only mean that incremental is disabled.
477-
// We don't cache stable hashes in non-incremental mode, because they are used
478-
// so rarely that the performance actually suffers.
479-
480-
let stable_hash: Fingerprint = {
481-
let mut hasher = StableHasher::new();
482-
hcx.while_hashing_spans(false, |hcx| {
483-
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
484-
kind.hash_stable(hcx, &mut hasher)
485-
})
486-
});
487-
hasher.finish()
488-
};
489-
stable_hash.hash_stable(hcx, hasher);
490-
} else {
491-
stable_hash.hash_stable(hcx, hasher);
492-
}
469+
kind.hash_stable(hcx, hasher)
493470
}
494471
}
495472

compiler/rustc_middle/src/ty/print/pretty.rs

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
33
use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable};
44
use rustc_apfloat::ieee::{Double, Single};
55
use rustc_data_structures::fx::FxHashMap;
6-
use rustc_data_structures::intern::Interned;
6+
use rustc_data_structures::intern::{InTy, Interned};
77
use rustc_data_structures::sso::SsoHashSet;
88
use rustc_hir as hir;
99
use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
@@ -1266,18 +1266,29 @@ pub trait PrettyPrinter<'tcx>:
12661266
ty::Ref(
12671267
_,
12681268
Ty(Interned(
1269-
ty::TyS {
1270-
kind:
1271-
ty::Array(
1272-
Ty(Interned(ty::TyS { kind: ty::Uint(ty::UintTy::U8), .. }, _)),
1273-
ty::Const(Interned(
1274-
ty::ConstS {
1275-
val: ty::ConstKind::Value(ConstValue::Scalar(int)),
1276-
..
1277-
},
1278-
_,
1279-
)),
1280-
),
1269+
InTy {
1270+
internee:
1271+
ty::TyS {
1272+
kind:
1273+
ty::Array(
1274+
Ty(Interned(
1275+
InTy {
1276+
internee:
1277+
ty::TyS { kind: ty::Uint(ty::UintTy::U8), .. },
1278+
..
1279+
},
1280+
_,
1281+
)),
1282+
ty::Const(Interned(
1283+
ty::ConstS {
1284+
val: ty::ConstKind::Value(ConstValue::Scalar(int)),
1285+
..
1286+
},
1287+
_,
1288+
)),
1289+
),
1290+
..
1291+
},
12811292
..
12821293
},
12831294
_,
@@ -1439,7 +1450,11 @@ pub trait PrettyPrinter<'tcx>:
14391450
// Byte/string slices, printed as (byte) string literals.
14401451
(
14411452
ConstValue::Slice { data, start, end },
1442-
ty::Ref(_, Ty(Interned(ty::TyS { kind: ty::Slice(t), .. }, _)), _),
1453+
ty::Ref(
1454+
_,
1455+
Ty(Interned(InTy { internee: ty::TyS { kind: ty::Slice(t), .. }, .. }, _)),
1456+
_,
1457+
),
14431458
) if *t == u8_type => {
14441459
// The `inspect` here is okay since we checked the bounds, and there are
14451460
// no relocations (we have an active slice reference here). We don't use
@@ -1450,7 +1465,11 @@ pub trait PrettyPrinter<'tcx>:
14501465
}
14511466
(
14521467
ConstValue::Slice { data, start, end },
1453-
ty::Ref(_, Ty(Interned(ty::TyS { kind: ty::Str, .. }, _)), _),
1468+
ty::Ref(
1469+
_,
1470+
Ty(Interned(InTy { internee: ty::TyS { kind: ty::Str, .. }, .. }, _)),
1471+
_,
1472+
),
14541473
) => {
14551474
// The `inspect` here is okay since we checked the bounds, and there are no
14561475
// relocations (we have an active `str` reference here). We don't use this

compiler/rustc_middle/src/ty/subst.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeVisitor}
66
use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
77
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
88

9-
use rustc_data_structures::intern::Interned;
9+
use rustc_data_structures::intern::{InTy, Interned};
1010
use rustc_hir::def_id::DefId;
1111
use rustc_macros::HashStable;
1212
use rustc_serialize::{self, Decodable, Encodable};
@@ -85,7 +85,7 @@ impl<'tcx> GenericArgKind<'tcx> {
8585
GenericArgKind::Type(ty) => {
8686
// Ensure we can use the tag bits.
8787
assert_eq!(mem::align_of_val(ty.0.0) & TAG_MASK, 0);
88-
(TYPE_TAG, ty.0.0 as *const ty::TyS<'tcx> as usize)
88+
(TYPE_TAG, ty.0.0 as *const InTy<ty::TyS<'tcx>> as usize)
8989
}
9090
GenericArgKind::Const(ct) => {
9191
// Ensure we can use the tag bits.
@@ -154,7 +154,7 @@ impl<'tcx> GenericArg<'tcx> {
154154
&*((ptr & !TAG_MASK) as *const ty::RegionKind),
155155
))),
156156
TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked(
157-
&*((ptr & !TAG_MASK) as *const ty::TyS<'tcx>),
157+
&*((ptr & !TAG_MASK) as *const InTy<ty::TyS<'tcx>>),
158158
))),
159159
CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked(
160160
&*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>),

compiler/rustc_middle/src/ty/util.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_apfloat::Float as _;
1313
use rustc_ast as ast;
1414
use rustc_attr::{self as attr, SignedInt, UnsignedInt};
1515
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
16-
use rustc_data_structures::intern::Interned;
16+
use rustc_data_structures::intern::{InTy, Interned};
1717
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
1818
use rustc_errors::ErrorGuaranteed;
1919
use rustc_hir as hir;
@@ -427,7 +427,7 @@ impl<'tcx> TyCtxt<'tcx> {
427427
!impl_generics.region_param(ebr, self).pure_wrt_drop
428428
}
429429
GenericArgKind::Type(Ty(Interned(
430-
ty::TyS { kind: ty::Param(ref pt), .. },
430+
InTy { internee: ty::TyS { kind: ty::Param(ref pt), .. }, .. },
431431
_,
432432
))) => !impl_generics.type_param(pt, self).pure_wrt_drop,
433433
GenericArgKind::Const(Const(Interned(

compiler/rustc_query_system/src/ich/hcx.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,4 +231,12 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
231231
}
232232
}
233233

234+
impl<'a> rustc_data_structures::intern::InternedHashingContext for StableHashingContext<'a> {
235+
fn with_def_path_and_no_spans(&mut self, f: impl FnOnce(&mut Self)) {
236+
self.while_hashing_spans(false, |hcx| {
237+
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| f(hcx))
238+
});
239+
}
240+
}
241+
234242
impl<'a> rustc_session::HashStableContext for StableHashingContext<'a> {}

0 commit comments

Comments
 (0)