Skip to content

Commit 8d6f527

Browse files
committed
Auto merge of rust-lang#94299 - oli-obk:stable_hash_ty, r=michaelwoerister
Caching the stable hash of Ty within itself Instead of computing stable hashes on types as needed, we compute it during interning. This way we can, when a hash is requested, just hash that hash, which is significantly faster than traversing the type itself. We only do this for incremental for now, as incremental is the only frequent user of stable hashing. As a next step we can try out * moving the hash and TypeFlags to Interner, so projections and regions get the same benefit (tho regions are not nested, so maybe that's not a good idea? Would be nice for dedup tho) * start comparing types via their stable hash instead of their address?
2 parents 4ce3749 + 5875d7b commit 8d6f527

File tree

4 files changed

+67
-13
lines changed

4 files changed

+67
-13
lines changed

compiler/rustc_middle/src/ty/context.rs

+34-5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use crate::ty::{
2424
RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy,
2525
};
2626
use rustc_ast as ast;
27+
use rustc_data_structures::fingerprint::Fingerprint;
2728
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
2829
use rustc_data_structures::intern::Interned;
2930
use rustc_data_structures::memmap::Mmap;
@@ -58,6 +59,7 @@ use rustc_span::{Span, DUMMY_SP};
5859
use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx};
5960
use rustc_target::spec::abi;
6061

62+
use rustc_type_ir::TypeFlags;
6163
use smallvec::SmallVec;
6264
use std::any::Any;
6365
use std::borrow::Borrow;
@@ -140,16 +142,39 @@ impl<'tcx> CtxtInterners<'tcx> {
140142
/// Interns a type.
141143
#[allow(rustc::usage_of_ty_tykind)]
142144
#[inline(never)]
143-
fn intern_ty(&self, kind: TyKind<'tcx>) -> Ty<'tcx> {
145+
fn intern_ty(
146+
&self,
147+
kind: TyKind<'tcx>,
148+
sess: &Session,
149+
resolutions: &ty::ResolverOutputs,
150+
) -> Ty<'tcx> {
144151
Ty(Interned::new_unchecked(
145152
self.type_
146153
.intern(kind, |kind| {
147154
let flags = super::flags::FlagComputation::for_kind(&kind);
148155

156+
// It's impossible to hash inference regions (and will ICE), so we don't need to try to cache them.
157+
// Without incremental, we rarely stable-hash types, so let's not do it proactively.
158+
let stable_hash = if flags.flags.intersects(TypeFlags::HAS_RE_INFER)
159+
|| sess.opts.incremental.is_none()
160+
{
161+
Fingerprint::ZERO
162+
} else {
163+
let mut hasher = StableHasher::new();
164+
let mut hcx = StableHashingContext::ignore_spans(
165+
sess,
166+
&resolutions.definitions,
167+
&*resolutions.cstore,
168+
);
169+
kind.hash_stable(&mut hcx, &mut hasher);
170+
hasher.finish()
171+
};
172+
149173
let ty_struct = TyS {
150174
kind,
151175
flags: flags.flags,
152176
outer_exclusive_binder: flags.outer_exclusive_binder,
177+
stable_hash,
153178
};
154179

155180
InternedInSet(self.arena.alloc(ty_struct))
@@ -887,8 +912,12 @@ pub enum UserType<'tcx> {
887912
}
888913

889914
impl<'tcx> CommonTypes<'tcx> {
890-
fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
891-
let mk = |ty| interners.intern_ty(ty);
915+
fn new(
916+
interners: &CtxtInterners<'tcx>,
917+
sess: &Session,
918+
resolutions: &ty::ResolverOutputs,
919+
) -> CommonTypes<'tcx> {
920+
let mk = |ty| interners.intern_ty(ty, sess, resolutions);
892921

893922
CommonTypes {
894923
unit: mk(Tuple(List::empty())),
@@ -1162,7 +1191,7 @@ impl<'tcx> TyCtxt<'tcx> {
11621191
s.fatal(&err);
11631192
});
11641193
let interners = CtxtInterners::new(arena);
1165-
let common_types = CommonTypes::new(&interners);
1194+
let common_types = CommonTypes::new(&interners, s, &resolutions);
11661195
let common_lifetimes = CommonLifetimes::new(&interners);
11671196
let common_consts = CommonConsts::new(&interners, &common_types);
11681197

@@ -2276,7 +2305,7 @@ impl<'tcx> TyCtxt<'tcx> {
22762305
#[allow(rustc::usage_of_ty_tykind)]
22772306
#[inline]
22782307
pub fn mk_ty(self, st: TyKind<'tcx>) -> Ty<'tcx> {
2279-
self.interners.intern_ty(st)
2308+
self.interners.intern_ty(st, self.sess, &self.gcx.untracked_resolutions)
22802309
}
22812310

22822311
#[inline]

compiler/rustc_middle/src/ty/mod.rs

+29-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub use self::Variance::*;
1717
pub use adt::*;
1818
pub use assoc::*;
1919
pub use generics::*;
20+
use rustc_data_structures::fingerprint::Fingerprint;
2021
pub use vtable::*;
2122

2223
use crate::metadata::ModChild;
@@ -30,7 +31,7 @@ use rustc_ast as ast;
3031
use rustc_attr as attr;
3132
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
3233
use rustc_data_structures::intern::Interned;
33-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
34+
use rustc_data_structures::stable_hasher::{HashStable, NodeIdHashingMode, StableHasher};
3435
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
3536
use rustc_hir as hir;
3637
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@@ -424,11 +425,15 @@ crate struct TyS<'tcx> {
424425
/// De Bruijn indices within the type are contained within `0..D`
425426
/// (exclusive).
426427
outer_exclusive_binder: ty::DebruijnIndex,
428+
429+
/// The stable hash of the type. This way hashing of types will not have to work
430+
/// on the address of the type anymore, but can instead just read this field
431+
stable_hash: Fingerprint,
427432
}
428433

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

433438
/// Use this rather than `TyS`, whenever possible.
434439
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -442,21 +447,41 @@ static BOOL_TYS: TyS<'static> = TyS {
442447
kind: ty::Bool,
443448
flags: TypeFlags::empty(),
444449
outer_exclusive_binder: DebruijnIndex::from_usize(0),
450+
stable_hash: Fingerprint::ZERO,
445451
};
446452

447453
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Ty<'tcx> {
448454
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
449455
let TyS {
450-
ref kind,
456+
kind,
451457

452458
// The other fields just provide fast access to information that is
453459
// also contained in `kind`, so no need to hash them.
454460
flags: _,
455461

456462
outer_exclusive_binder: _,
463+
464+
stable_hash,
457465
} = self.0.0;
458466

459-
kind.hash_stable(hcx, hasher);
467+
if *stable_hash == Fingerprint::ZERO {
468+
// No cached hash available. This can only mean that incremental is disabled.
469+
// We don't cache stable hashes in non-incremental mode, because they are used
470+
// so rarely that the performance actually suffers.
471+
472+
let stable_hash: Fingerprint = {
473+
let mut hasher = StableHasher::new();
474+
hcx.while_hashing_spans(false, |hcx| {
475+
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
476+
kind.hash_stable(hcx, &mut hasher)
477+
})
478+
});
479+
hasher.finish()
480+
};
481+
stable_hash.hash_stable(hcx, hasher);
482+
} else {
483+
stable_hash.hash_stable(hcx, hasher);
484+
}
460485
}
461486
}
462487

src/test/ui/symbol-names/basic.legacy.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error: symbol-name(_ZN5basic4main17h611df9c6948c15f7E)
1+
error: symbol-name(_ZN5basic4main17h87acd86b3a6f1754E)
22
--> $DIR/basic.rs:8:1
33
|
44
LL | #[rustc_symbol_name]
55
| ^^^^^^^^^^^^^^^^^^^^
66

7-
error: demangling(basic::main::h611df9c6948c15f7)
7+
error: demangling(basic::main::h87acd86b3a6f1754)
88
--> $DIR/basic.rs:8:1
99
|
1010
LL | #[rustc_symbol_name]

src/test/ui/symbol-names/issue-60925.legacy.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h5425dadb5b1e5fb6E)
1+
error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h8d22952c45e20d65E)
22
--> $DIR/issue-60925.rs:21:9
33
|
44
LL | #[rustc_symbol_name]
55
| ^^^^^^^^^^^^^^^^^^^^
66

7-
error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h5425dadb5b1e5fb6)
7+
error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h8d22952c45e20d65)
88
--> $DIR/issue-60925.rs:21:9
99
|
1010
LL | #[rustc_symbol_name]

0 commit comments

Comments
 (0)