diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 19d8856dc6ce4..f9435682e5394 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -24,6 +24,7 @@ use crate::ty::{ RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy, }; use rustc_ast as ast; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::memmap::Mmap; @@ -58,6 +59,7 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; +use rustc_type_ir::TypeFlags; use smallvec::SmallVec; use std::any::Any; use std::borrow::Borrow; @@ -140,16 +142,39 @@ impl<'tcx> CtxtInterners<'tcx> { /// Interns a type. #[allow(rustc::usage_of_ty_tykind)] #[inline(never)] - fn intern_ty(&self, kind: TyKind<'tcx>) -> Ty<'tcx> { + fn intern_ty( + &self, + kind: TyKind<'tcx>, + sess: &Session, + resolutions: &ty::ResolverOutputs, + ) -> Ty<'tcx> { Ty(Interned::new_unchecked( self.type_ .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_kind(&kind); + // It's impossible to hash inference regions (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::HAS_RE_INFER) + || sess.opts.incremental.is_none() + { + Fingerprint::ZERO + } else { + let mut hasher = StableHasher::new(); + let mut hcx = StableHashingContext::ignore_spans( + sess, + &resolutions.definitions, + &*resolutions.cstore, + ); + kind.hash_stable(&mut hcx, &mut hasher); + hasher.finish() + }; + let ty_struct = TyS { kind, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, + stable_hash, }; InternedInSet(self.arena.alloc(ty_struct)) @@ -887,8 +912,12 @@ pub enum UserType<'tcx> { } impl<'tcx> CommonTypes<'tcx> { - fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { - let mk = |ty| interners.intern_ty(ty); + fn new( + interners: &CtxtInterners<'tcx>, + sess: &Session, + resolutions: &ty::ResolverOutputs, + ) -> CommonTypes<'tcx> { + let mk = |ty| interners.intern_ty(ty, sess, resolutions); CommonTypes { unit: mk(Tuple(List::empty())), @@ -1162,7 +1191,7 @@ impl<'tcx> TyCtxt<'tcx> { s.fatal(&err); }); let interners = CtxtInterners::new(arena); - let common_types = CommonTypes::new(&interners); + let common_types = CommonTypes::new(&interners, s, &resolutions); let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); @@ -2276,7 +2305,7 @@ impl<'tcx> TyCtxt<'tcx> { #[allow(rustc::usage_of_ty_tykind)] #[inline] pub fn mk_ty(self, st: TyKind<'tcx>) -> Ty<'tcx> { - self.interners.intern_ty(st) + self.interners.intern_ty(st, self.sess, &self.gcx.untracked_resolutions) } #[inline] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 88c993d98e242..6edcfbcdc6cee 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -17,6 +17,7 @@ pub use self::Variance::*; pub use adt::*; pub use assoc::*; pub use generics::*; +use rustc_data_structures::fingerprint::Fingerprint; pub use vtable::*; use crate::metadata::ModChild; @@ -30,7 +31,7 @@ use rustc_ast as ast; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::intern::Interned; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, NodeIdHashingMode, StableHasher}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -424,11 +425,15 @@ crate struct TyS<'tcx> { /// De Bruijn indices within the type are contained within `0..D` /// (exclusive). outer_exclusive_binder: ty::DebruijnIndex, + + /// The stable hash of the type. This way hashing of types will not have to work + /// on the address of the type anymore, but can instead just read this field + stable_hash: Fingerprint, } // `TyS` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(TyS<'_>, 40); +static_assert_size!(TyS<'_>, 56); /// Use this rather than `TyS`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -442,21 +447,41 @@ static BOOL_TYS: TyS<'static> = TyS { kind: ty::Bool, flags: TypeFlags::empty(), outer_exclusive_binder: DebruijnIndex::from_usize(0), + stable_hash: Fingerprint::ZERO, }; impl<'a, 'tcx> HashStable> for Ty<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let TyS { - ref kind, + 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: _, + + stable_hash, } = self.0.0; - kind.hash_stable(hcx, hasher); + if *stable_hash == Fingerprint::ZERO { + // 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. + + let stable_hash: Fingerprint = { + let mut hasher = StableHasher::new(); + hcx.while_hashing_spans(false, |hcx| { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + kind.hash_stable(hcx, &mut hasher) + }) + }); + hasher.finish() + }; + stable_hash.hash_stable(hcx, hasher); + } else { + stable_hash.hash_stable(hcx, hasher); + } } } diff --git a/src/test/ui/symbol-names/basic.legacy.stderr b/src/test/ui/symbol-names/basic.legacy.stderr index 429e28e5241dc..e4d58d3ccdb29 100644 --- a/src/test/ui/symbol-names/basic.legacy.stderr +++ b/src/test/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17h611df9c6948c15f7E) +error: symbol-name(_ZN5basic4main17h87acd86b3a6f1754E) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::h611df9c6948c15f7) +error: demangling(basic::main::h87acd86b3a6f1754) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr index 0e36747fb8071..c987ebc534302 100644 --- a/src/test/ui/symbol-names/issue-60925.legacy.stderr +++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h5425dadb5b1e5fb6E) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h8d22952c45e20d65E) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::h5425dadb5b1e5fb6) +error: demangling(issue_60925::foo::Foo::foo::h8d22952c45e20d65) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name]