diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs index 7a320b10b60..009b5d5340a 100644 --- a/compiler/rustc_data_structures/src/intern.rs +++ b/compiler/rustc_data_structures/src/intern.rs @@ -4,6 +4,8 @@ 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; @@ -108,5 +110,87 @@ where } } +/// A helper trait so that `Interned` things can cache stable hashes reproducibly. +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 WithStableHash { + pub internee: T, + pub stable_hash: Fingerprint, +} + +impl PartialEq for WithStableHash { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.internee.eq(&other.internee) + } +} + +impl Eq for WithStableHash {} + +impl PartialOrd for WithStableHash { + fn partial_cmp(&self, other: &WithStableHash) -> Option { + Some(self.internee.cmp(&other.internee)) + } +} + +impl Ord for WithStableHash { + fn cmp(&self, other: &WithStableHash) -> Ordering { + self.internee.cmp(&other.internee) + } +} + +impl Deref for WithStableHash { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + &self.internee + } +} + +impl Hash for WithStableHash { + #[inline] + fn hash(&self, s: &mut H) { + self.internee.hash(s) + } +} + +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. + // 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(); + hcx.with_def_path_and_no_spans(|hcx| 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_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index 97e219ab61d..c8236ce79c0 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -2,7 +2,6 @@ use crate::infer::free_regions::FreeRegionMap; use crate::infer::{GenericKind, InferCtxt}; use crate::traits::query::OutlivesBound; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::intern::Interned; use rustc_hir as hir; use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region}; @@ -164,12 +163,6 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { for outlives_bound in outlives_bounds { debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound); match outlives_bound { - OutlivesBound::RegionSubRegion( - r_a @ (Region(Interned(ReEarlyBound(_), _)) | Region(Interned(ReFree(_), _))), - Region(Interned(ReVar(vid_b), _)), - ) => { - infcx.expect("no infcx provided but region vars found").add_given(r_a, *vid_b); - } OutlivesBound::RegionSubParam(r_a, param_b) => { self.region_bound_pairs_accum.push((r_a, GenericKind::Param(param_b))); } @@ -178,17 +171,23 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> { .push((r_a, GenericKind::Projection(projection_b))); } OutlivesBound::RegionSubRegion(r_a, r_b) => { - // In principle, we could record (and take - // advantage of) every relationship here, but - // we are also free not to -- it simply means - // strictly less that we can successfully type - // check. Right now we only look for things - // relationships between free regions. (It may - // also be that we should revise our inference - // system to be more general and to make use - // of *every* relationship that arises here, - // but presently we do not.) - self.free_region_map.relate_regions(r_a, r_b); + if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) { + infcx + .expect("no infcx provided but region vars found") + .add_given(r_a, vid_b); + } else { + // In principle, we could record (and take + // advantage of) every relationship here, but + // we are also free not to -- it simply means + // strictly less that we can successfully type + // check. Right now we only look for things + // relationships between free regions. (It may + // also be that we should revise our inference + // system to be more general and to make use + // of *every* relationship that arises here, + // but presently we do not.) + self.free_region_map.relate_regions(r_a, r_b); + } } } } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 170dd113f6d..7c90cbb9092 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_middle::ty::TyS<'tcx>, + [] 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 6ca8f8b1309..a26de409b3c 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::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, TyS<'tcx>>, + type_: InternedSet<'tcx, WithStableHash>>, substs: InternedSet<'tcx, InternalSubsts<'tcx>>, canonical_var_infos: InternedSet<'tcx, List>>, region: InternedSet<'tcx, RegionKind>, @@ -178,10 +178,11 @@ impl<'tcx> CtxtInterners<'tcx> { kind, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, - stable_hash, }; - InternedInSet(self.arena.alloc(ty_struct)) + InternedInSet( + self.arena.alloc(WithStableHash { internee: ty_struct, stable_hash }), + ) }) .0, )) @@ -2048,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, TyS<'tcx>> { +impl<'tcx> Borrow> for InternedInSet<'tcx, WithStableHash>> { fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { &self.0.kind } } -impl<'tcx> PartialEq for InternedInSet<'tcx, TyS<'tcx>> { - fn eq(&self, other: &InternedInSet<'tcx, TyS<'tcx>>) -> 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, TyS<'tcx>> {} +impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash>> {} -impl<'tcx> Hash for InternedInSet<'tcx, TyS<'tcx>> { +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/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index e278efa3d8b..f6d139fe59d 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -5,7 +5,6 @@ use crate::ty::subst::Subst; use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable}; use rustc_ast as ast; use rustc_attr as attr; -use rustc_data_structures::intern::Interned; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::BitSet; @@ -503,42 +502,34 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } // Two non-ZST fields, and they're both scalars. - ( - Some(( - i, - &TyAndLayout { - layout: Layout(Interned(&LayoutS { abi: Abi::Scalar(a), .. }, _)), - .. - }, - )), - Some(( - j, - &TyAndLayout { - layout: Layout(Interned(&LayoutS { abi: Abi::Scalar(b), .. }, _)), - .. - }, - )), - None, - ) => { - // Order by the memory placement, not source order. - let ((i, a), (j, b)) = - if offsets[i] < offsets[j] { ((i, a), (j, b)) } else { ((j, b), (i, a)) }; - let pair = self.scalar_pair(a, b); - let pair_offsets = match pair.fields { - FieldsShape::Arbitrary { ref offsets, ref memory_index } => { - assert_eq!(memory_index, &[0, 1]); - offsets + (Some((i, a)), Some((j, b)), None) => { + match (a.abi, b.abi) { + (Abi::Scalar(a), Abi::Scalar(b)) => { + // Order by the memory placement, not source order. + let ((i, a), (j, b)) = if offsets[i] < offsets[j] { + ((i, a), (j, b)) + } else { + ((j, b), (i, a)) + }; + let pair = self.scalar_pair(a, b); + let pair_offsets = match pair.fields { + FieldsShape::Arbitrary { ref offsets, ref memory_index } => { + assert_eq!(memory_index, &[0, 1]); + offsets + } + _ => bug!(), + }; + if offsets[i] == pair_offsets[0] + && offsets[j] == pair_offsets[1] + && align == pair.align + && size == pair.size + { + // We can use `ScalarPair` only when it matches our + // already computed layout (including `#[repr(C)]`). + abi = pair.abi; + } } - _ => bug!(), - }; - if offsets[i] == pair_offsets[0] - && offsets[j] == pair_offsets[1] - && align == pair.align - && size == pair.size - { - // We can use `ScalarPair` only when it matches our - // already computed layout (including `#[repr(C)]`). - abi = pair.abi; + _ => {} } } @@ -791,10 +782,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } // Extract the number of elements from the layout of the array field: - let Ok(TyAndLayout { - layout: Layout(Interned(LayoutS { fields: FieldsShape::Array { count, .. }, .. }, _)), - .. - }) = self.layout_of(f0_ty) else { + let FieldsShape::Array { count, .. } = self.layout_of(f0_ty)?.layout.fields() else { return Err(LayoutError::Unknown(ty)); }; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6e3dc92a233..399817d59c4 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -31,8 +31,8 @@ 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::Interned; -use rustc_data_structures::stable_hasher::{HashStable, NodeIdHashingMode, StableHasher}; +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; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -438,32 +438,36 @@ 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<'_>, 56); +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)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_diagnostic_item = "Ty"] #[rustc_pass_by_value] -pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>); +pub struct Ty<'tcx>(Interned<'tcx, WithStableHash>>); // Statics only used for internal testing. -pub static BOOL_TY: Ty<'static> = Ty(Interned::new_unchecked(&BOOL_TYS)); -static BOOL_TYS: TyS<'static> = TyS { +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(), outer_exclusive_binder: DebruijnIndex::from_usize(0), - stable_hash: Fingerprint::ZERO, }; -impl<'a, 'tcx> HashStable> for Ty<'tcx> { +impl<'a, 'tcx> HashStable> for TyS<'tcx> { + #[inline] fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let TyS { kind, @@ -473,28 +477,9 @@ impl<'a, 'tcx> HashStable> for Ty<'tcx> { flags: _, outer_exclusive_binder: _, + } = self; - stable_hash, - } = self.0.0; - - 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); - } + kind.hash_stable(hcx, hasher) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 9a9c529f245..4379adb604e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3,7 +3,6 @@ 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::Interned; use rustc_data_structures::sso::SsoHashSet; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; @@ -1263,60 +1262,52 @@ pub trait PrettyPrinter<'tcx>: let (alloc_id, offset) = ptr.into_parts(); match ty.kind() { // Byte strings (&[u8; N]) - ty::Ref( - _, - Ty(Interned( - ty::TyS { - kind: - ty::Array( - Ty(Interned(ty::TyS { kind: ty::Uint(ty::UintTy::U8), .. }, _)), - ty::Const(Interned( - ty::ConstS { - val: ty::ConstKind::Value(ConstValue::Scalar(int)), - .. - }, - _, - )), - ), - .. - }, - _, - )), - _, - ) => match self.tcx().get_global_alloc(alloc_id) { - Some(GlobalAlloc::Memory(alloc)) => { - let len = int.assert_bits(self.tcx().data_layout.pointer_size); - let range = AllocRange { start: offset, size: Size::from_bytes(len) }; - if let Ok(byte_str) = alloc.inner().get_bytes(&self.tcx(), range) { - p!(pretty_print_byte_str(byte_str)) - } else { - p!("") + ty::Ref(_, inner, _) => { + if let ty::Array(elem, len) = inner.kind() { + if let ty::Uint(ty::UintTy::U8) = elem.kind() { + if let ty::ConstKind::Value(ConstValue::Scalar(int)) = len.val() { + match self.tcx().get_global_alloc(alloc_id) { + Some(GlobalAlloc::Memory(alloc)) => { + let len = int.assert_bits(self.tcx().data_layout.pointer_size); + let range = + AllocRange { start: offset, size: Size::from_bytes(len) }; + if let Ok(byte_str) = + alloc.inner().get_bytes(&self.tcx(), range) + { + p!(pretty_print_byte_str(byte_str)) + } else { + p!("") + } + } + // FIXME: for statics and functions, we could in principle print more detail. + Some(GlobalAlloc::Static(def_id)) => { + p!(write("", def_id)) + } + Some(GlobalAlloc::Function(_)) => p!(""), + None => p!(""), + } + return Ok(self); + } } } - // FIXME: for statics and functions, we could in principle print more detail. - Some(GlobalAlloc::Static(def_id)) => p!(write("", def_id)), - Some(GlobalAlloc::Function(_)) => p!(""), - None => p!(""), - }, + } ty::FnPtr(_) => { // FIXME: We should probably have a helper method to share code with the "Byte strings" // printing above (which also has to handle pointers to all sorts of things). - match self.tcx().get_global_alloc(alloc_id) { - Some(GlobalAlloc::Function(instance)) => { - self = self.typed_value( - |this| this.print_value_path(instance.def_id(), instance.substs), - |this| this.print_type(ty), - " as ", - )?; - } - _ => self = self.pretty_print_const_pointer(ptr, ty, print_ty)?, + if let Some(GlobalAlloc::Function(instance)) = self.tcx().get_global_alloc(alloc_id) + { + self = self.typed_value( + |this| this.print_value_path(instance.def_id(), instance.substs), + |this| this.print_type(ty), + " as ", + )?; + return Ok(self); } } - // Any pointer values not covered by a branch above - _ => { - self = self.pretty_print_const_pointer(ptr, ty, print_ty)?; - } + _ => {} } + // Any pointer values not covered by a branch above + self = self.pretty_print_const_pointer(ptr, ty, print_ty)?; Ok(self) } @@ -1437,28 +1428,31 @@ pub trait PrettyPrinter<'tcx>: match (ct, ty.kind()) { // Byte/string slices, printed as (byte) string literals. - ( - ConstValue::Slice { data, start, end }, - ty::Ref(_, Ty(Interned(ty::TyS { kind: ty::Slice(t), .. }, _)), _), - ) if *t == u8_type => { - // The `inspect` here is okay since we checked the bounds, and there are - // no relocations (we have an active slice reference here). We don't use - // this result to affect interpreter execution. - let byte_str = - data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end); - self.pretty_print_byte_str(byte_str) - } - ( - ConstValue::Slice { data, start, end }, - ty::Ref(_, Ty(Interned(ty::TyS { kind: ty::Str, .. }, _)), _), - ) => { - // The `inspect` here is okay since we checked the bounds, and there are no - // relocations (we have an active `str` reference here). We don't use this - // result to affect interpreter execution. - let slice = - data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end); - p!(write("{:?}", String::from_utf8_lossy(slice))); - Ok(self) + (ConstValue::Slice { data, start, end }, ty::Ref(_, inner, _)) => { + match inner.kind() { + ty::Slice(t) => { + if *t == u8_type { + // The `inspect` here is okay since we checked the bounds, and there are + // no relocations (we have an active slice reference here). We don't use + // this result to affect interpreter execution. + let byte_str = data + .inner() + .inspect_with_uninit_and_ptr_outside_interpreter(start..end); + return self.pretty_print_byte_str(byte_str); + } + } + ty::Str => { + // The `inspect` here is okay since we checked the bounds, and there are no + // relocations (we have an active `str` reference here). We don't use this + // result to affect interpreter execution. + let slice = data + .inner() + .inspect_with_uninit_and_ptr_outside_interpreter(start..end); + p!(write("{:?}", String::from_utf8_lossy(slice))); + return Ok(self); + } + _ => {} + } } (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => { let n = n.val().try_to_bits(self.tcx().data_layout.pointer_size).unwrap(); @@ -1468,7 +1462,7 @@ pub trait PrettyPrinter<'tcx>: let byte_str = alloc.inner().get_bytes(&self.tcx(), range).unwrap(); p!("*"); p!(pretty_print_byte_str(byte_str)); - Ok(self) + return Ok(self); } // Aggregates, printed as array/tuple/struct/variant construction syntax. @@ -1545,22 +1539,24 @@ pub trait PrettyPrinter<'tcx>: _ => unreachable!(), } - Ok(self) + return Ok(self); } - (ConstValue::Scalar(scalar), _) => self.pretty_print_const_scalar(scalar, ty, print_ty), + (ConstValue::Scalar(scalar), _) => { + return self.pretty_print_const_scalar(scalar, ty, print_ty); + } // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading // their fields instead of just dumping the memory. - _ => { - // fallback - p!(write("{:?}", ct)); - if print_ty { - p!(": ", print(ty)); - } - Ok(self) - } + _ => {} } + + // fallback + p!(write("{:?}", ct)); + if print_ty { + p!(": ", print(ty)); + } + Ok(self) } } diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 0a6cb276f75..46b938ea93b 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::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 ty::TyS<'tcx> 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 ty::TyS<'tcx>), + &*((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 7d9a917d04c..a9749716ce8 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -6,14 +6,12 @@ use crate::ty::layout::IntegerExt; use crate::ty::query::TyCtxtAt; use crate::ty::subst::{GenericArgKind, Subst, SubstsRef}; use crate::ty::{ - self, Const, DebruijnIndex, DefIdTree, List, ReEarlyBound, Region, Ty, TyCtxt, TyKind::*, - TypeFoldable, + self, Const, DebruijnIndex, DefIdTree, List, ReEarlyBound, Ty, TyCtxt, TyKind::*, TypeFoldable, }; 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::Interned; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; @@ -423,24 +421,25 @@ impl<'tcx> TyCtxt<'tcx> { let result = iter::zip(item_substs, impl_substs) .filter(|&(_, k)| { match k.unpack() { - GenericArgKind::Lifetime(Region(Interned(ReEarlyBound(ref ebr), _))) => { - !impl_generics.region_param(ebr, self).pure_wrt_drop - } - GenericArgKind::Type(Ty(Interned( - ty::TyS { kind: ty::Param(ref pt), .. }, - _, - ))) => !impl_generics.type_param(pt, self).pure_wrt_drop, - GenericArgKind::Const(Const(Interned( - ty::ConstS { val: ty::ConstKind::Param(ref pc), .. }, - _, - ))) => !impl_generics.const_param(pc, self).pure_wrt_drop, - GenericArgKind::Lifetime(_) - | GenericArgKind::Type(_) - | GenericArgKind::Const(_) => { - // Not a type, const or region param: this should be reported - // as an error. - false - } + GenericArgKind::Lifetime(region) => match region.kind() { + ReEarlyBound(ref ebr) => { + !impl_generics.region_param(ebr, self).pure_wrt_drop + } + // Error: not a region param + _ => false, + }, + GenericArgKind::Type(ty) => match ty.kind() { + ty::Param(ref pt) => !impl_generics.type_param(pt, self).pure_wrt_drop, + // Error: not a type param + _ => false, + }, + GenericArgKind::Const(ct) => match ct.val() { + ty::ConstKind::Param(ref pc) => { + !impl_generics.const_param(pc, self).pure_wrt_drop + } + // Error: not a const param + _ => false, + }, } }) .map(|(item_param, _)| item_param) diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index 76e21be17bc..a073bf71057 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -231,4 +231,12 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { } } +impl<'a> rustc_data_structures::intern::InternedHashingContext for StableHashingContext<'a> { + fn with_def_path_and_no_spans(&mut self, f: impl FnOnce(&mut Self)) { + self.while_hashing_spans(false, |hcx| { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| f(hcx)) + }); + } +} + impl<'a> rustc_session::HashStableContext for StableHashingContext<'a> {} diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 2b9cc75f1b7..302b8b79156 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -8,7 +8,6 @@ //! In this case we try to build an abstract representation of this constant using //! `thir_abstract_const` which can then be checked for structural equality with other //! generic constants mentioned in the `caller_bounds` of the current environment. -use rustc_data_structures::intern::Interned; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::DefKind; use rustc_index::vec::IndexVec; @@ -414,14 +413,12 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { self.recurse_build(self.body_id)?; for n in self.nodes.iter() { - if let Node::Leaf(ty::Const(Interned( - ty::ConstS { val: ty::ConstKind::Unevaluated(ct), ty: _ }, - _, - ))) = n - { - // `AbstractConst`s should not contain any promoteds as they require references which - // are not allowed. - assert_eq!(ct.promoted, None); + if let Node::Leaf(ct) = n { + if let ty::ConstKind::Unevaluated(ct) = ct.val() { + // `AbstractConst`s should not contain any promoteds as they require references which + // are not allowed. + assert_eq!(ct.promoted, None); + } } } diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs index 42eec177649..5dab0bb7a13 100644 --- a/compiler/rustc_typeck/src/check/place_op.rs +++ b/compiler/rustc_typeck/src/check/place_op.rs @@ -1,7 +1,6 @@ use crate::check::method::MethodCallee; use crate::check::{has_expected_num_generic_args, FnCtxt, PlaceOp}; use rustc_ast as ast; -use rustc_data_structures::intern::Interned; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -126,9 +125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) = index_expr.kind { match adjusted_ty.kind() { - ty::Adt(ty::AdtDef(Interned(ty::AdtDefData { did, .. }, _)), _) - if self.tcx.is_diagnostic_item(sym::Vec, *did) => - { + ty::Adt(def, _) if self.tcx.is_diagnostic_item(sym::Vec, def.did()) => { return self.negative_index(adjusted_ty, index_expr.span, base_expr); } ty::Slice(_) | ty::Array(_, _) => { diff --git a/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs index df780747a0c..a8f9c189ade 100644 --- a/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use if_chain::if_chain; use rustc_ast::ast::LitKind; -use rustc_data_structures::intern::Interned; use rustc_hir::{Expr, ExprKind, PathSegment}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; @@ -56,8 +55,8 @@ fn check_case_sensitive_file_extension_comparison(ctx: &LateContext<'_>, expr: & ty::Str => { return Some(span); }, - ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did, .. }, _)), _) => { - if ctx.tcx.is_diagnostic_item(sym::String, did) { + ty::Adt(def, _) => { + if ctx.tcx.is_diagnostic_item(sym::String, def.did()) { return Some(span); } },