diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e9135b7163025..729827ea7b31c 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -521,6 +521,7 @@ pub struct Crate { /// /// E.g., the '..' in `#[name(..)]`. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum NestedMetaItem { /// A full MetaItem, for recursive meta items. MetaItem(MetaItem), @@ -534,6 +535,7 @@ pub enum NestedMetaItem { /// /// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct MetaItem { pub path: Path, pub kind: MetaItemKind, @@ -544,6 +546,7 @@ pub struct MetaItem { /// /// E.g., `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum MetaItemKind { /// Word meta item. /// @@ -1527,6 +1530,7 @@ impl MacCall { /// Arguments passed to an attribute or a function-like macro. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum MacArgs { /// No arguments - `#[attr]`. Empty, @@ -1602,6 +1606,7 @@ impl MacDelimiter { /// Represents a macro definition. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct MacroDef { pub body: P, /// `true` if macro was defined with `macro_rules`. @@ -1621,6 +1626,7 @@ pub enum StrStyle { /// An AST literal. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Lit { /// The original literal token as written in source code. pub token: token::Lit, @@ -2425,6 +2431,7 @@ impl rustc_serialize::Decodable for AttrId { } #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct AttrItem { pub path: Path, pub args: MacArgs, diff --git a/compiler/rustc_ast/src/ptr.rs b/compiler/rustc_ast/src/ptr.rs index 70dbda8222445..6c3c2eb23b855 100644 --- a/compiler/rustc_ast/src/ptr.rs +++ b/compiler/rustc_ast/src/ptr.rs @@ -30,6 +30,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; /// An owned smart pointer. +#[derive(HashStableEq)] pub struct P { ptr: Box, } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index db066d7c6a519..b65dc4083e9ca 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -178,6 +178,7 @@ fn ident_can_begin_type(name: Symbol, span: Span, is_raw: bool) -> bool { } #[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum TokenKind { /* Expression-operator symbols. */ Eq, @@ -246,6 +247,7 @@ pub enum TokenKind { rustc_data_structures::static_assert_size!(TokenKind, 16); #[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Token { pub kind: TokenKind, pub span: Span, diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 2174378a560d3..822b7ddf381a2 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -38,6 +38,7 @@ use std::{fmt, iter, mem}; /// The RHS of an MBE macro is the only place `SubstNt`s are substituted. /// Nothing special happens to misnamed or misplaced `SubstNt`s. #[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum TokenTree { /// A single token. Token(Token), diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 9bb8db076a8d6..504fa688f8feb 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -107,6 +107,7 @@ bitflags::bitflags! { } #[derive(Clone, Debug, Encodable, Decodable, HashStable)] +#[stable_hasher(no_hash_stable_eq)] pub struct NativeLib { pub kind: NativeLibKind, pub name: Option, diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs index c79a5ebf0933b..7e50b0b785739 100644 --- a/compiler/rustc_data_structures/src/intern.rs +++ b/compiler/rustc_data_structures/src/intern.rs @@ -3,6 +3,8 @@ use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::ptr; +use crate::stable_hasher::HashStableEq; + mod private { #[derive(Clone, Copy, Debug)] pub struct PrivateZst; @@ -52,6 +54,14 @@ impl<'a, T> Deref for Interned<'a, T> { } } +// FIXME - is this right? Should we try to enforce this somehow? +impl<'a, T: HashStableEq> HashStableEq for Interned<'a, T> { + fn hash_stable_eq(&self, other: &Self) -> bool { + // Pointer equality implies equality, due to the uniqueness constraint. + ptr::eq(self.0, other.0) + } +} + impl<'a, T> PartialEq for Interned<'a, T> { #[inline] fn eq(&self, other: &Self) -> bool { diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs index 9efea1228ab29..9bfb3ee6c9086 100644 --- a/compiler/rustc_data_structures/src/sorted_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map.rs @@ -1,4 +1,4 @@ -use crate::stable_hasher::{HashStable, StableHasher}; +use crate::stable_hasher::{HashStable, HashStableEq, StableHasher}; use std::borrow::Borrow; use std::cmp::Ordering; use std::iter::FromIterator; @@ -298,5 +298,11 @@ impl, V: HashStable, CTX> HashStable for SortedMap< } } +impl HashStableEq for SortedMap { + fn hash_stable_eq(&self, other: &Self) -> bool { + self.data.hash_stable_eq(&other.data) + } +} + #[cfg(test)] mod tests; diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index 31d6a42cf2884..e62fe952dd2d7 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -199,6 +199,10 @@ pub trait HashStable { fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher); } +pub trait HashStableEq { + fn hash_stable_eq(&self, other: &Self) -> bool; +} + /// Implement this for types that can be turned into stable keys like, for /// example, for DefId that can be converted to a DefPathHash. This is used for /// bringing maps into a predictable order before hashing them. @@ -218,6 +222,25 @@ macro_rules! impl_stable_hash_via_hash { ::std::hash::Hash::hash(self, hasher); } } + + impl $crate::stable_hasher::HashStableEq for $t { + #[inline] + fn hash_stable_eq(&self, other: &Self) -> bool { + self == other + } + } + }; +} + +#[macro_export] +macro_rules! impl_hash_stable_eq_via_eq { + ($t:ty) => { + impl ::rustc_data_structures::stable_hasher::HashStableEq for $t { + #[inline] + fn hash_stable_eq(&self, other: &Self) -> bool { + self == other + } + } }; } @@ -257,6 +280,24 @@ impl HashStable for ::std::num::NonZeroUsize { } } +impl HashStableEq for ::std::num::NonZeroUsize { + fn hash_stable_eq(&self, other: &Self) -> bool { + self.get().hash_stable_eq(&other.get()) + } +} + +impl HashStableEq for ::std::num::NonZeroU32 { + fn hash_stable_eq(&self, other: &Self) -> bool { + self.get().hash_stable_eq(&other.get()) + } +} + +impl HashStableEq for ::std::num::NonZeroU64 { + fn hash_stable_eq(&self, other: &Self) -> bool { + self.get().hash_stable_eq(&other.get()) + } +} + impl HashStable for f32 { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { let val: u32 = unsafe { ::std::mem::transmute(*self) }; @@ -277,6 +318,20 @@ impl HashStable for ::std::cmp::Ordering { } } +impl HashStableEq for (T1, T2) { + fn hash_stable_eq(&self, other: &Self) -> bool { + self.0.hash_stable_eq(&other.0) && self.1.hash_stable_eq(&other.1) + } +} + +impl HashStableEq for (T1, T2, T3) { + fn hash_stable_eq(&self, other: &Self) -> bool { + self.0.hash_stable_eq(&other.0) + && self.1.hash_stable_eq(&other.1) + && self.2.hash_stable_eq(&other.2) + } +} + impl, CTX> HashStable for (T1,) { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { let (ref _0,) = *self; @@ -322,6 +377,26 @@ where } } +impl HashStableEq for [T] { + fn hash_stable_eq(&self, other: &Self) -> bool { + if self.len() != other.len() { + return false; + } + for (first, second) in self.iter().zip(other.iter()) { + if !first.hash_stable_eq(second) { + return false; + } + } + true + } +} + +impl HashStableEq for [T; N] { + fn hash_stable_eq(&self, other: &Self) -> bool { + (self[..]).hash_stable_eq(other) + } +} + impl, CTX> HashStable for [T] { default fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { self.len().hash_stable(ctx, hasher); @@ -331,6 +406,15 @@ impl, CTX> HashStable for [T] { } } +impl, CTX, const N: usize> HashStable for [T; N] { + default fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + self.len().hash_stable(ctx, hasher); + for item in self { + item.hash_stable(ctx, hasher); + } + } +} + impl HashStable for [u8] { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { self.len().hash_stable(ctx, hasher); @@ -345,6 +429,32 @@ impl, CTX> HashStable for Vec { } } +impl HashStableEq for Vec { + #[inline] + fn hash_stable_eq(&self, other: &Self) -> bool { + (&self[..]).hash_stable_eq(other) + } +} + +impl HashStableEq + for indexmap::IndexMap +{ + fn hash_stable_eq(&self, other: &Self) -> bool { + if self.len() != other.len() { + return false; + } + // Equal maps will have equal iteration orders + // FIXME -is that actually right? + self.iter().zip(other.iter()).all(|(first, second)| first.hash_stable_eq(&second)) + } +} + +impl HashStableEq for std::marker::PhantomData { + fn hash_stable_eq(&self, _other: &Self) -> bool { + true + } +} + impl HashStable for indexmap::IndexMap where K: HashStable + Eq + Hash, @@ -384,6 +494,15 @@ where } } +impl HashStableEq for SmallVec +where + ::Item: HashStableEq, +{ + fn hash_stable_eq(&self, other: &Self) -> bool { + (&self[..]).hash_stable_eq(other) + } +} + impl, CTX> HashStable for Box { #[inline] fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { @@ -391,6 +510,12 @@ impl, CTX> HashStable for Box { } } +impl HashStableEq for Box { + fn hash_stable_eq(&self, other: &Self) -> bool { + (**self).hash_stable_eq(other) + } +} + impl, CTX> HashStable for ::std::rc::Rc { #[inline] fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { @@ -405,6 +530,18 @@ impl, CTX> HashStable for ::std::sync::Arc { } } +impl HashStableEq for ::std::rc::Rc { + fn hash_stable_eq(&self, other: &Self) -> bool { + (**self).hash_stable_eq(other) + } +} + +impl HashStableEq for ::std::sync::Arc { + fn hash_stable_eq(&self, other: &Self) -> bool { + (**self).hash_stable_eq(other) + } +} + impl HashStable for str { #[inline] fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { @@ -419,6 +556,20 @@ impl HashStable for String { } } +impl HashStableEq for str { + #[inline] + fn hash_stable_eq(&self, other: &Self) -> bool { + self.as_bytes().hash_stable_eq(other.as_bytes()) + } +} + +impl HashStableEq for String { + #[inline] + fn hash_stable_eq(&self, other: &Self) -> bool { + (&self[..]).hash_stable_eq(other) + } +} + impl ToStableHashKey for String { type KeyType = String; #[inline] @@ -434,6 +585,32 @@ impl HashStable for bool { } } +impl HashStableEq for Option { + fn hash_stable_eq(&self, other: &Self) -> bool { + match (self, other) { + (Some(first), Some(second)) => first.hash_stable_eq(second), + (None, None) => true, + _ => false, + } + } +} + +impl HashStableEq for Result { + fn hash_stable_eq(&self, other: &Self) -> bool { + match (self, other) { + (Ok(first), Ok(second)) => first.hash_stable_eq(second), + (Err(first), Err(second)) => first.hash_stable_eq(second), + _ => false, + } + } +} + +impl HashStableEq for bool { + fn hash_stable_eq(&self, other: &Self) -> bool { + self == other + } +} + impl HashStable for Option where T: HashStable, @@ -474,6 +651,12 @@ where } } +impl<'a, T: HashStableEq + ?Sized> HashStableEq for &'a T { + fn hash_stable_eq(&self, other: &Self) -> bool { + (**self).hash_stable_eq(other) + } +} + impl HashStable for ::std::mem::Discriminant { #[inline] fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) { @@ -504,6 +687,12 @@ where } } +impl HashStableEq for vec::IndexVec { + fn hash_stable_eq(&self, other: &Self) -> bool { + self.iter().as_slice().hash_stable_eq(other.iter().as_slice()) + } +} + impl HashStable for bit_set::BitSet { fn hash_stable(&self, _ctx: &mut CTX, hasher: &mut StableHasher) { ::std::hash::Hash::hash(self, hasher); @@ -544,6 +733,49 @@ where } } +impl HashStableEq for ::std::collections::HashMap +where + K: HashStableEq + Eq + Hash, + V: HashStableEq, + R: BuildHasher, +{ + fn hash_stable_eq(&self, other: &Self) -> bool { + if self.len() != other.len() { + return false; + } + self.iter().all(|(key, value)| { + match other.get_key_value(key) { + Some((other_key, other_value)) => { + // Compare the key, since the `PartailEq` impl + // used by the map may ignore information + key.hash_stable_eq(other_key) && value.hash_stable_eq(other_value) + } + _ => false, + } + }) + } +} + +impl HashStableEq for ::std::collections::HashSet +where + K: HashStableEq + Eq + Hash, + R: BuildHasher, +{ + fn hash_stable_eq(&self, other: &Self) -> bool { + if self.len() != other.len() { + return false; + } + self.iter().all(|key| { + match other.get(key) { + // Compare the key, since the `PartailEq` impl + // used by the map may ignore information + Some(other_key) => key.hash_stable_eq(other_key), + None => false, + } + }) + } +} + impl HashStable for ::std::collections::HashSet where K: ToStableHashKey + Eq, diff --git a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs index e1d3e0bd35a67..dc35f3cea1e68 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs @@ -1,5 +1,5 @@ use super::{Pointer, Tag}; -use crate::stable_hasher::{HashStable, StableHasher}; +use crate::stable_hasher::{HashStable, HashStableEq, StableHasher}; use std::fmt; use std::marker::PhantomData; use std::num::NonZeroUsize; @@ -161,6 +161,16 @@ where { } +impl HashStableEq for CopyTaggedPtr +where + P: Pointer, + T: Tag, +{ + fn hash_stable_eq(&self, other: &Self) -> bool { + self == other + } +} + impl std::hash::Hash for CopyTaggedPtr where P: Pointer, diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index e99f61d034fb8..0367b667acf7c 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -255,6 +255,7 @@ impl DefKind { // #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum Res { /// Definition having a unique ID (`DefId`), corresponds to something defined in user code. /// diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 0961d0131d07c..b547f7924b1c4 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -25,6 +25,7 @@ use smallvec::SmallVec; use std::fmt; #[derive(Copy, Clone, Encodable, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Lifetime { pub hir_id: HirId, pub span: Span, @@ -40,6 +41,7 @@ pub struct Lifetime { #[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)] #[derive(HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum ParamName { /// Some user-given name like `T` or `'x`. Plain(Ident), @@ -86,6 +88,7 @@ impl ParamName { #[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)] #[derive(HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum LifetimeName { /// User-given names or fresh (synthetic) names. Param(ParamName), @@ -186,6 +189,7 @@ impl Lifetime { /// `std::cmp::PartialEq`. It's represented as a sequence of identifiers, /// along with a bunch of supporting information. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Path<'hir> { pub span: Span, /// The resolution for the path. @@ -203,6 +207,7 @@ impl Path<'_> { /// A segment of a path: an identifier, an optional lifetime, and a set of /// types. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct PathSegment<'hir> { /// The identifier portion of this path segment. pub ident: Ident, @@ -249,12 +254,14 @@ impl<'hir> PathSegment<'hir> { } #[derive(Encodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct ConstArg { pub value: AnonConst, pub span: Span, } #[derive(Encodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct InferArg { pub hir_id: HirId, pub span: Span, @@ -267,6 +274,7 @@ impl InferArg { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum GenericArg<'hir> { Lifetime(Lifetime), Type(Ty<'hir>), @@ -324,6 +332,7 @@ impl GenericArg<'_> { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct GenericArgs<'hir> { /// The generic arguments for this path segment. pub args: &'hir [GenericArg<'hir>], @@ -435,6 +444,7 @@ pub enum TraitBoundModifier { /// the "special" built-in traits (see `middle::lang_items`) and /// detects `Copy`, `Send` and `Sync`. #[derive(Clone, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum GenericBound<'hir> { Trait(PolyTraitRef<'hir>, TraitBoundModifier), // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem` @@ -465,6 +475,7 @@ impl GenericBound<'_> { pub type GenericBounds<'hir> = &'hir [GenericBound<'hir>]; #[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum LifetimeParamKind { // Indicates that the lifetime definition was explicitly declared (e.g., in // `fn foo<'a>(x: &'a u8) -> &'a u8 { x }`). @@ -484,6 +495,7 @@ pub enum LifetimeParamKind { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum GenericParamKind<'hir> { /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`). Lifetime { @@ -501,6 +513,7 @@ pub enum GenericParamKind<'hir> { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct GenericParam<'hir> { pub hir_id: HirId, pub name: ParamName, @@ -539,6 +552,7 @@ pub struct GenericParamCount { /// Represents lifetimes and type parameters attached to a declaration /// of a function, enum, trait, etc. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Generics<'hir> { pub params: &'hir [GenericParam<'hir>], pub where_clause: WhereClause<'hir>, @@ -574,6 +588,7 @@ impl<'hir> Generics<'hir> { /// A where-clause in a definition. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct WhereClause<'hir> { pub predicates: &'hir [WherePredicate<'hir>], // Only valid if predicates aren't empty. @@ -601,6 +616,7 @@ impl WhereClause<'_> { /// A single predicate in a where-clause. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum WherePredicate<'hir> { /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). BoundPredicate(WhereBoundPredicate<'hir>), @@ -622,6 +638,7 @@ impl<'hir> WherePredicate<'hir> { /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct WhereBoundPredicate<'hir> { pub span: Span, /// Any generics from a `for` binding. @@ -649,6 +666,7 @@ impl<'hir> WhereBoundPredicate<'hir> { /// A lifetime predicate (e.g., `'a: 'b + 'c`). #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct WhereRegionPredicate<'hir> { pub span: Span, pub lifetime: Lifetime, @@ -657,6 +675,7 @@ pub struct WhereRegionPredicate<'hir> { /// An equality predicate (e.g., `T = int`); currently unsupported. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct WhereEqPredicate<'hir> { pub hir_id: HirId, pub span: Span, @@ -721,6 +740,7 @@ impl<'tcx> OwnerNodes<'tcx> { /// Full information resulting from lowering an AST node. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct OwnerInfo<'hir> { /// Contents of the HIR. pub nodes: OwnerNodes<'hir>, @@ -788,6 +808,7 @@ pub struct Crate<'hir> { /// `targeted_by_break` field will be `true`) and may be `unsafe` by means of /// the `rules` being anything but `DefaultBlock`. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Block<'hir> { /// Statements in a block. pub stmts: &'hir [Stmt<'hir>], @@ -806,6 +827,7 @@ pub struct Block<'hir> { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Pat<'hir> { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -887,6 +909,7 @@ impl<'hir> Pat<'hir> { /// are treated the same as` x: x, y: ref y, z: ref mut z`, /// except `is_shorthand` is true. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct PatField<'hir> { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -902,6 +925,7 @@ pub struct PatField<'hir> { /// that this is not the final binding *mode* that we infer after type /// inference. #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum BindingAnnotation { /// No binding annotation given: this means that the final binding mode /// will depend on whether we have skipped through a `&` reference @@ -938,6 +962,7 @@ impl fmt::Display for RangeEnd { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum PatKind<'hir> { /// Represents a wildcard pattern (i.e., `_`). Wild, @@ -994,6 +1019,7 @@ pub enum PatKind<'hir> { } #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum BinOpKind { /// The `+` operator (addition). Add, @@ -1122,6 +1148,7 @@ impl Into for BinOpKind { pub type BinOp = Spanned; #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum UnOp { /// The `*` operator (deferencing). Deref, @@ -1148,6 +1175,7 @@ impl UnOp { /// A statement. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Stmt<'hir> { pub hir_id: HirId, pub kind: StmtKind<'hir>, @@ -1156,6 +1184,7 @@ pub struct Stmt<'hir> { /// The contents of a statement. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum StmtKind<'hir> { /// A local (`let`) binding. Local(&'hir Local<'hir>), @@ -1172,6 +1201,7 @@ pub enum StmtKind<'hir> { /// Represents a `let` statement (i.e., `let : = ;`). #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Local<'hir> { pub pat: &'hir Pat<'hir>, /// Type annotation, if any (otherwise the type will be inferred). @@ -1188,6 +1218,7 @@ pub struct Local<'hir> { /// Represents a single arm of a `match` expression, e.g. /// ` (if ) => `. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Arm<'hir> { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -1206,6 +1237,7 @@ pub struct Arm<'hir> { /// In an if-let, imagine it as `if (let = ) { ... }`; in a let-else, it is part of the /// desugaring to if-let. Only let-else supports the type annotation at present. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Let<'hir> { pub hir_id: HirId, pub span: Span, @@ -1215,6 +1247,7 @@ pub struct Let<'hir> { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum Guard<'hir> { If(&'hir Expr<'hir>), // FIXME use hir::Let for this. @@ -1222,6 +1255,7 @@ pub enum Guard<'hir> { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct ExprField<'hir> { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -1232,18 +1266,20 @@ pub struct ExprField<'hir> { } #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum BlockCheckMode { DefaultBlock, UnsafeBlock(UnsafeSource), } #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum UnsafeSource { CompilerGenerated, UserProvided, } -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug, HashStableEq)] pub struct BodyId { pub hir_id: HirId, } @@ -1692,6 +1728,7 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum ExprKind<'hir> { /// A `box x` expression. Box(&'hir Expr<'hir>), @@ -1820,6 +1857,7 @@ pub enum ExprKind<'hir> { /// /// [`qpath_res`]: ../rustc_middle/ty/struct.TypeckResults.html#method.qpath_res #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum QPath<'hir> { /// Path to a definition, optionally "fully-qualified" with a `Self` /// type, if the path points to an associated item in a trait. @@ -2012,6 +2050,7 @@ impl From for YieldSource { // N.B., if you change this, you'll probably want to change the corresponding // type structure in middle/ty.rs as well. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct MutTy<'hir> { pub ty: &'hir Ty<'hir>, pub mutbl: Mutability, @@ -2020,6 +2059,7 @@ pub struct MutTy<'hir> { /// Represents a function's signature in a trait declaration, /// trait implementation, or a free function. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct FnSig<'hir> { pub header: FnHeader, pub decl: &'hir FnDecl<'hir>, @@ -2029,7 +2069,8 @@ pub struct FnSig<'hir> { // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStableEq)] +#[stable_hasher(no_hash_stable_eq)] pub struct TraitItemId { pub def_id: LocalDefId, } @@ -2069,6 +2110,7 @@ impl TraitItem<'_> { /// Represents a trait method's body (or just argument names). #[derive(Encodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum TraitFn<'hir> { /// No default body in the trait, just a signature. Required(&'hir [Ident]), @@ -2079,6 +2121,7 @@ pub enum TraitFn<'hir> { /// Represents a trait method or associated constant or type #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum TraitItemKind<'hir> { /// An associated constant with an optional value (otherwise `impl`s must contain a value). Const(&'hir Ty<'hir>, Option), @@ -2092,7 +2135,7 @@ pub enum TraitItemKind<'hir> { // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStableEq)] pub struct ImplItemId { pub def_id: LocalDefId, } @@ -2130,6 +2173,7 @@ impl ImplItem<'_> { /// Represents various kinds of content within an `impl`. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum ImplItemKind<'hir> { /// An associated constant of the given type, set to the constant result /// of the expression. @@ -2159,6 +2203,7 @@ pub const FN_OUTPUT_NAME: Symbol = sym::Output; /// } /// ``` #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct TypeBinding<'hir> { pub hir_id: HirId, pub ident: Ident, @@ -2168,6 +2213,7 @@ pub struct TypeBinding<'hir> { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum Term<'hir> { Ty(&'hir Ty<'hir>), Const(AnonConst), @@ -2187,6 +2233,7 @@ impl<'hir> From for Term<'hir> { // Represents the two kinds of type bindings. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum TypeBindingKind<'hir> { /// E.g., `Foo`. Constraint { bounds: &'hir [GenericBound<'hir>] }, @@ -2219,6 +2266,7 @@ pub struct Ty<'hir> { /// Not represented directly in the AST; referred to by name through a `ty_path`. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum PrimTy { Int(IntTy), Uint(UintTy), @@ -2305,6 +2353,7 @@ impl PrimTy { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct BareFnTy<'hir> { pub unsafety: Unsafety, pub abi: Abi, @@ -2314,6 +2363,7 @@ pub struct BareFnTy<'hir> { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct OpaqueTy<'hir> { pub generics: Generics<'hir>, pub bounds: GenericBounds<'hir>, @@ -2322,6 +2372,7 @@ pub struct OpaqueTy<'hir> { /// From whence the opaque type came. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum OpaqueTyOrigin { /// `-> impl Trait` FnReturn(LocalDefId), @@ -2333,6 +2384,7 @@ pub enum OpaqueTyOrigin { /// The various kinds of types recognized by the compiler. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum TyKind<'hir> { /// A variable length slice (i.e., `[T]`). Slice(&'hir Ty<'hir>), @@ -2371,6 +2423,7 @@ pub enum TyKind<'hir> { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum InlineAsmOperand<'hir> { In { reg: InlineAsmRegOrRegClass, @@ -2420,6 +2473,7 @@ impl<'hir> InlineAsmOperand<'hir> { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct InlineAsm<'hir> { pub template: &'hir [InlineAsmTemplatePiece], pub template_strs: &'hir [(Symbol, Option, Span)], @@ -2430,6 +2484,7 @@ pub struct InlineAsm<'hir> { /// Represents a parameter in a function header. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Param<'hir> { pub hir_id: HirId, pub pat: &'hir Pat<'hir>, @@ -2439,6 +2494,7 @@ pub struct Param<'hir> { /// Represents the header (not the body) of a function declaration. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct FnDecl<'hir> { /// The types of the function's parameters. /// @@ -2504,6 +2560,7 @@ impl Defaultness { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum FnRetTy<'hir> { /// Return type is not specified. /// @@ -2526,6 +2583,7 @@ impl FnRetTy<'_> { } #[derive(Encodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Mod<'hir> { /// A span from the first token past `{` to the last token until `}`. /// For `mod foo;`, the inner span ranges from the first token @@ -2535,11 +2593,13 @@ pub struct Mod<'hir> { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct EnumDef<'hir> { pub variants: &'hir [Variant<'hir>], } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Variant<'hir> { /// Name of the variant. pub ident: Ident, @@ -2554,6 +2614,7 @@ pub struct Variant<'hir> { } #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum UseKind { /// One import, e.g., `use foo::bar` or `use foo::bar as baz`. /// Also produced for each element of a list `use`, e.g. @@ -2576,6 +2637,7 @@ pub enum UseKind { /// trait being referred to but just a unique `HirId` that serves as a key /// within the resolution map. #[derive(Clone, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct TraitRef<'hir> { pub path: &'hir Path<'hir>, // Don't hash the `ref_id`. It is tracked via the thing it is used to access. @@ -2595,6 +2657,7 @@ impl TraitRef<'_> { } #[derive(Clone, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct PolyTraitRef<'hir> { /// The `'a` in `for<'a> Foo<&'a T>`. pub bound_generic_params: &'hir [GenericParam<'hir>], @@ -2629,6 +2692,7 @@ impl VisibilityKind<'_> { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct FieldDef<'hir> { pub span: Span, pub ident: Ident, @@ -2647,6 +2711,7 @@ impl FieldDef<'_> { /// Fields and constructor IDs of enum variants and structs. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum VariantData<'hir> { /// A struct variant. /// @@ -2683,7 +2748,7 @@ impl<'hir> VariantData<'hir> { // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, Hash, HashStableEq)] pub struct ItemId { pub def_id: LocalDefId, } @@ -2780,6 +2845,7 @@ impl FnHeader { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum ItemKind<'hir> { /// An `extern crate` item, with optional *original* crate name if the crate was renamed. /// @@ -2827,6 +2893,7 @@ pub enum ItemKind<'hir> { } #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Impl<'hir> { pub unsafety: Unsafety, pub polarity: ImplPolarity, @@ -2906,6 +2973,7 @@ pub struct TraitItemRef { /// passes to find the impl they want without loading the ID (which /// means fewer edges in the incremental compilation graph). #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct ImplItemRef { pub id: ImplItemId, pub ident: Ident, @@ -2926,7 +2994,7 @@ pub enum AssocItemKind { // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStableEq)] pub struct ForeignItemId { pub def_id: LocalDefId, } @@ -2946,6 +3014,7 @@ impl ForeignItemId { /// passes to find the impl they want without loading the ID (which /// means fewer edges in the incremental compilation graph). #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct ForeignItemRef { pub id: ForeignItemId, pub ident: Ident, @@ -2975,6 +3044,7 @@ impl ForeignItem<'_> { /// An item within an `extern` block. #[derive(Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum ForeignItemKind<'hir> { /// A foreign function. Fn(&'hir FnDecl<'hir>, &'hir [Ident], Generics<'hir>), @@ -2986,6 +3056,7 @@ pub enum ForeignItemKind<'hir> { /// A variable captured by a closure. #[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Upvar { // First span where it is accessed (there can be multiple). pub span: Span, @@ -3001,6 +3072,7 @@ pub struct TraitCandidate { } #[derive(Copy, Clone, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum OwnerNode<'hir> { Item(&'hir Item<'hir>), ForeignItem(&'hir ForeignItem<'hir>), @@ -3140,6 +3212,7 @@ impl<'hir> Into> for OwnerNode<'hir> { } #[derive(Copy, Clone, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum Node<'hir> { Param(&'hir Param<'hir>), Item(&'hir Item<'hir>), diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index dee391b9cce21..74f9b9de62f92 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -11,7 +11,7 @@ use std::fmt; /// the `local_id` part of the `HirId` changing, which is a very useful property in /// incremental compilation where we have to persist things through changes to /// the code base. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStableEq)] #[derive(Encodable, Decodable)] pub struct HirId { pub owner: LocalDefId, diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index b299e71c9c4c4..71329b05a1560 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -44,7 +44,7 @@ macro_rules! language_item_table { enum_from_u32! { /// A representation of all the valid language items in Rust. - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)] + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, HashStableEq)] pub enum LangItem { $( #[doc = concat!("The `", stringify!($name), "` lang item.")] @@ -84,6 +84,7 @@ macro_rules! language_item_table { /// All of the language items, defined or not. /// Defined lang items can come from the current crate or its dependencies. #[derive(HashStable_Generic, Debug)] + #[stable_hasher(no_hash_stable_eq)] pub struct LanguageItems { /// Mappings from lang items to their possibly found [`DefId`]s. /// The index corresponds to the order in [`LangItem`]. diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs index 63bdcea87f817..dffb4530502b3 100644 --- a/compiler/rustc_macros/src/hash_stable.rs +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -41,7 +41,27 @@ fn parse_attributes(field: &syn::Field) -> Attributes { attrs } +fn no_hash_stable_eq(s: &synstructure::Structure<'_>) -> bool { + for attr in &s.ast().attrs { + if let Ok(meta) = attr.parse_meta() { + if !meta.path().is_ident("stable_hasher") { + continue; + } + let arg: syn::Ident = attr.parse_args().unwrap(); + if arg.to_string() == "no_hash_stable_eq" { + return true; + } else { + panic!("Unexpected argument {:?}", arg); + } + } + } + return false; +} + pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { + let orig = s.clone(); + let no_eq = no_hash_stable_eq(&orig); + let generic: syn::GenericParam = parse_quote!(__CTX); s.add_bounds(synstructure::AddBounds::Generics); s.add_impl_generic(generic); @@ -69,7 +89,7 @@ pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_ma syn::Data::Union(_) => panic!("cannot derive on union"), }; - s.bound_impl( + let impl_body = s.bound_impl( quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>), quote! { #[inline] @@ -81,10 +101,81 @@ pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_ma match *self { #body } } }, + ); + + if no_eq { + impl_body + } else { + let eq_impl = hash_stable_eq_derive(orig); + //println!("Eq impl:\n{}", eq_impl); + quote! { + #impl_body + #eq_impl + } + } +} + +pub fn hash_stable_eq_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { + let mut other = s.clone(); + other.binding_name(|_bi, i| { + Ident::new(&format!("__binding_other_{}", i), proc_macro2::Span::call_site()) + }); + + let eq_body: proc_macro2::TokenStream = s + .variants() + .iter() + .zip(other.variants()) + .map(|(variant1, variant2)| { + let first_pat = variant1.pat(); + let second_pat = variant2.pat(); + + let compare = std::iter::once(quote! { true }).chain( + variant1.bindings().iter().zip(variant2.bindings()).map(|(binding1, binding2)| { + let attrs = parse_attributes(binding1.ast()); + if attrs.ignore { + quote! { true } + } else if let Some(project) = attrs.project { + quote! { + ::rustc_data_structures::stable_hasher::HashStableEq::hash_stable_eq( + #binding1.#project, #binding2.#project + ) + } + } else { + quote! { + ::rustc_data_structures::stable_hasher::HashStableEq::hash_stable_eq( + #binding1, #binding2 + ) + } + } + }), + ); + quote! { + (#first_pat, #second_pat) => { + #(#compare)&&* + } + } + }) + .collect(); + + s.add_bounds(synstructure::AddBounds::Generics); + s.bound_impl( + quote!(::rustc_data_structures::stable_hasher::HashStableEq), + quote! { + #[inline] + fn hash_stable_eq(&self, other: &Self) -> bool { + match (self, other) { + #eq_body + _ => false + } + } + }, ) } pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { + let orig = s.clone(); + let no_eq = no_hash_stable_eq(&orig); + let generic: syn::GenericParam = parse_quote!('__ctx); s.add_bounds(synstructure::AddBounds::Generics); s.add_impl_generic(generic); @@ -111,7 +202,7 @@ pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::To syn::Data::Union(_) => panic!("cannot derive on union"), }; - s.bound_impl( + let impl_body = s.bound_impl( quote!( ::rustc_data_structures::stable_hasher::HashStable< ::rustc_query_system::ich::StableHashingContext<'__ctx>, @@ -127,5 +218,15 @@ pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::To match *self { #body } } }, - ) + ); + + if no_eq { + impl_body + } else { + let eq_impl = hash_stable_eq_derive(orig); + quote! { + #impl_body + #eq_impl + } + } } diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 152ae159aed44..b3ce685ad7551 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -25,6 +25,7 @@ pub fn symbols(input: TokenStream) -> TokenStream { } decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive); +decl_derive!([HashStableEq, attributes(stable_hasher)] => hash_stable::hash_stable_eq_derive); decl_derive!( [HashStable_Generic, attributes(stable_hasher)] => hash_stable::hash_stable_generic_derive diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 17c77c1bbd891..08479cdf108c0 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -53,6 +53,7 @@ impl LintLevelSource { pub type LevelAndSource = (Level, LintLevelSource); #[derive(Debug, HashStable)] +#[stable_hasher(no_hash_stable_eq)] pub struct LintLevelSets { pub list: IndexVec, pub lint_cap: Level, @@ -66,6 +67,8 @@ rustc_index::newtype_index! { } #[derive(Debug, HashStable)] +#[stable_hasher(no_hash_stable_eq)] +// FIXME - how is LintId implementing HashStable ? pub struct LintSet { // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which // flag. diff --git a/compiler/rustc_middle/src/metadata.rs b/compiler/rustc_middle/src/metadata.rs index 6dcdc58c72d82..a947472837613 100644 --- a/compiler/rustc_middle/src/metadata.rs +++ b/compiler/rustc_middle/src/metadata.rs @@ -11,6 +11,7 @@ use rustc_span::Span; /// Module child can be either a proper item or a reexport (including private imports). /// In case of reexport all the fields describe the reexport item itself, not what it refers to. #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] +#[stable_hasher(no_hash_stable_eq)] pub struct ModChild { /// Name of the item. pub ident: Ident, diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 54eb2dc9e2890..e145cdba96470 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -4,6 +4,7 @@ use rustc_span::symbol::Symbol; use rustc_target::spec::SanitizerSet; #[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)] +#[stable_hasher(no_hash_stable_eq)] pub struct CodegenFnAttrs { pub flags: CodegenFnAttrFlags, /// Parsed representation of the `#[inline]` attribute diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index a36c9b6ed7304..14591f5cda713 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -496,7 +496,18 @@ impl Allocation { } /// "Relocations" stores the provenance information of pointers stored in memory. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] +#[derive( + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Debug, + TyEncodable, + TyDecodable, + HashStableEq +)] pub struct Relocations(SortedMap); impl Relocations { diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 66f2c6e78a2e8..2a4a9c5b91d5b 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -177,7 +177,7 @@ pub enum LitToConstError { Reported, } -#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd, HashStableEq)] pub struct AllocId(pub NonZeroU64); // We want the `Debug` output to be readable as it is used by `derive(Debug)` for diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 7e5f8018dfc42..d844e943626ee 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -195,6 +195,7 @@ impl<'tcx> MirSource<'tcx> { } #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable)] +#[stable_hasher(no_hash_stable_eq)] pub struct GeneratorInfo<'tcx> { /// The yield type of the function, if it is a generator. pub yield_ty: Option>, @@ -212,6 +213,7 @@ pub struct GeneratorInfo<'tcx> { /// The lowered representation of a single function. #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable)] +#[stable_hasher(no_hash_stable_eq)] pub struct Body<'tcx> { /// A list of basic blocks. References to basic block use a newtyped index type [`BasicBlock`] /// that indexes into this vector. @@ -882,6 +884,7 @@ pub struct BlockTailInfo { /// This can be a binding declared by the user, a temporary inserted by the compiler, a function /// argument, or the return place. #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[stable_hasher(no_hash_stable_eq)] pub struct LocalDecl<'tcx> { /// Whether this is a mutable binding (i.e., `let x` or `let mut x`). /// @@ -1017,6 +1020,7 @@ static_assert_size!(LocalDecl<'_>, 56); /// Not used for non-StaticRef temporaries, the return place, or anonymous /// function parameters. #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[stable_hasher(no_hash_stable_eq)] pub enum LocalInfo<'tcx> { /// A user-defined local variable or function parameter /// diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 5c616425957df..366e43975d856 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -132,6 +132,7 @@ rustc_index::newtype_index! { /// The layout of generator state. #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)] +#[stable_hasher(no_hash_stable_eq)] pub struct GeneratorLayout<'tcx> { /// The type of every local stored inside the generator. pub field_tys: IndexVec>, @@ -207,6 +208,7 @@ impl Debug for GeneratorLayout<'_> { } #[derive(Debug, TyEncodable, TyDecodable, HashStable)] +#[stable_hasher(no_hash_stable_eq)] pub struct BorrowCheckResult<'tcx> { /// All the opaque types that are restricted to concrete types /// by this function. Unlike the value in `TypeckResults`, this has diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index 03a6daaf8aa4f..7fa420f45a9b6 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -22,6 +22,7 @@ use rustc_span::symbol::sym; /// default items amongst other things. In the simple "chain" rule, every impl /// has at most one parent. #[derive(TyEncodable, TyDecodable, HashStable, Debug)] +#[stable_hasher(no_hash_stable_eq)] pub struct Graph { /// All impls have a parent; the "root" impls have as their parent the `def_id` /// of the trait. diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 40fbea7c3d91f..f7997036b4a97 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -5,7 +5,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::HashingControls; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, HashStableEq, StableHasher}; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; @@ -125,6 +125,12 @@ impl PartialEq for AdtDef { impl Eq for AdtDef {} +impl HashStableEq for AdtDef { + fn hash_stable_eq(&self, other: &Self) -> bool { + self == other + } +} + /// There should be only one AdtDef for each `did`, therefore /// it is fine to implement `Hash` only based on `did`. impl Hash for AdtDef { diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 49f846562a3cc..c109e9d9dddce 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -111,6 +111,7 @@ impl AssocKind { /// it is relatively expensive. Instead, items are indexed by `Symbol` and hygienic comparison is /// done only on items with the same name. #[derive(Debug, Clone, PartialEq, HashStable)] +#[stable_hasher(no_hash_stable_eq)] pub struct AssocItems<'tcx> { pub(super) items: SortedIndexMultiMap, } diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index de45e1bb851ac..69c57e977853e 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -1,5 +1,6 @@ use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; +use rustc_data_structures::stable_hasher::HashStableEq; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_target::abi::Size; use std::convert::{TryFrom, TryInto}; @@ -117,6 +118,7 @@ impl std::fmt::Debug for ConstInt { /// /// This is a packed struct in order to allow this type to be optimally embedded in enums /// (like Scalar). +// FIXME - how are these impls correct if HashStable isnt'??? #[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(packed)] pub struct ScalarInt { @@ -139,6 +141,13 @@ impl crate::ty::HashStable for ScalarInt { } } +impl HashStableEq for ScalarInt { + fn hash_stable_eq(&self, other: &Self) -> bool { + let other_data = other.data; + { self.data }.hash_stable_eq(&other_data) && self.size.hash_stable_eq(&other.size) + } +} + impl Encodable for ScalarInt { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u128(self.data)?; diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 983057bff95d6..da2010630bb3c 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -17,7 +17,19 @@ pub type SimplifiedType = SimplifiedTypeGen; /// because we sometimes need to use SimplifiedTypeGen values as stable sorting /// keys (in which case we use a DefPathHash as id-type) but in the general case /// the non-stable but fast to construct DefId-version is the better choice. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)] +#[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + TyEncodable, + TyDecodable, + HashStableEq +)] pub enum SimplifiedTypeGen where D: Copy + Debug + Eq, diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index adba7d131592e..702ec6cd0991a 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -1,4 +1,5 @@ use crate::arena::Arena; +use rustc_data_structures::stable_hasher::HashStableEq; use rustc_serialize::{Encodable, Encoder}; use std::alloc::Layout; use std::cmp::Ordering; @@ -134,6 +135,12 @@ impl PartialEq for List { } } +impl HashStableEq for List { + fn hash_stable_eq(&self, other: &Self) -> bool { + (&self[..]).hash_stable_eq(other) + } +} + impl Eq for List {} impl Ord for List diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f0b7f2a653f45..22dfe8a9b11bb 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -30,7 +30,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, HashStableEq, StableHasher}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -444,6 +444,22 @@ static BOOL_TYS: TyS<'static> = TyS { outer_exclusive_binder: DebruijnIndex::from_usize(0), }; +impl<'tcx> HashStableEq for Ty<'tcx> { + fn hash_stable_eq(&self, other: &Self) -> bool { + let TyS { + ref kind, + + // The other fields just provide fast access to information that is + // also contained in `kind`, so no need to compare them. + flags: _, + + outer_exclusive_binder: _, + } = self.0.0; + + kind.hash_stable_eq(other.kind()) + } +} + impl<'a, 'tcx> HashStable> for Ty<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let TyS { @@ -489,6 +505,12 @@ static_assert_size!(PredicateS<'_>, 56); #[cfg_attr(not(bootstrap), rustc_pass_by_value)] pub struct Predicate<'tcx>(Interned<'tcx, PredicateS<'tcx>>); +impl<'tcx> HashStableEq for Predicate<'tcx> { + fn hash_stable_eq(&self, other: &Self) -> bool { + self == other + } +} + impl<'tcx> Predicate<'tcx> { /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. #[inline] @@ -1104,7 +1126,19 @@ impl UniverseIndex { /// identified by both a universe, as well as a name residing within that universe. Distinct bound /// regions/types/consts within the same universe simply have an unknown relationship to one /// another. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)] +#[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + Hash, + TyEncodable, + TyDecodable, + PartialOrd, + Ord, + HashStableEq +)] pub struct Placeholder { pub universe: UniverseIndex, pub name: T, @@ -1265,7 +1299,7 @@ impl WithOptConstParam { /// When type checking, we use the `ParamEnv` to track /// details about the set of where-clauses that are in scope at this /// particular point. -#[derive(Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Hash, PartialEq, Eq, HashStableEq)] pub struct ParamEnv<'tcx> { /// This packs both caller bounds and the reveal enum into one pointer. /// @@ -1500,7 +1534,7 @@ impl<'tcx> PolyTraitRef<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HashStableEq)] pub struct ParamEnvAnd<'tcx, T> { pub param_env: ParamEnv<'tcx>, pub value: T, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9835211a74865..2fc066efdd65e 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1074,7 +1074,7 @@ pub enum BoundVariableKind { /// e.g., `liberate_late_bound_regions`). /// /// `Decodable` and `Encodable` are implemented for `Binder` using the `impl_binder_encode_decode!` macro. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, HashStableEq)] pub struct Binder<'tcx, T>(T, &'tcx List); impl<'tcx, T> Binder<'tcx, T> @@ -1518,7 +1518,7 @@ impl<'tcx> fmt::Debug for Region<'tcx> { /// [1]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/ /// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/ /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html -#[derive(Clone, PartialEq, Eq, Hash, Copy, TyEncodable, TyDecodable, PartialOrd, Ord)] +#[derive(Clone, PartialEq, Eq, Hash, Copy, TyEncodable, TyDecodable, PartialOrd, Ord, HashStableEq)] pub enum RegionKind { /// Region bound in a type or fn declaration which will be /// substituted 'early' -- that is, at the same time when type @@ -1556,7 +1556,19 @@ pub enum RegionKind { ReErased, } -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)] +#[derive( + Copy, + Clone, + PartialEq, + Eq, + Hash, + TyEncodable, + TyDecodable, + Debug, + PartialOrd, + Ord, + HashStableEq +)] pub struct EarlyBoundRegion { pub def_id: DefId, pub index: u32, @@ -1564,7 +1576,7 @@ pub struct EarlyBoundRegion { } /// A **`const`** **v**ariable **ID**. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable, HashStableEq)] pub struct ConstVid<'tcx> { pub index: u32, pub phantom: PhantomData<&'tcx ()>, @@ -1572,6 +1584,7 @@ pub struct ConstVid<'tcx> { rustc_index::newtype_index! { /// A **region** (lifetime) **v**ariable **ID**. + #[derive(HashStableEq)] pub struct RegionVid { DEBUG_FORMAT = custom, } @@ -1584,6 +1597,7 @@ impl Atom for RegionVid { } rustc_index::newtype_index! { + #[derive(HashStableEq)] pub struct BoundVar { .. } } diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 7dccef5e3ef0f..19356c6518415 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -8,7 +8,7 @@ use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; use rustc_data_structures::intern::Interned; use rustc_hir::def_id::DefId; -use rustc_macros::HashStable; +use rustc_macros::{HashStable, HashStableEq}; use rustc_serialize::{self, Decodable, Encodable}; use rustc_span::{Span, DUMMY_SP}; use smallvec::SmallVec; @@ -29,7 +29,7 @@ use std::ops::ControlFlow; /// /// Note: the `PartialEq`, `Eq` and `Hash` derives are only valid because `Ty`, /// `Region` and `Const` are all interned. -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStableEq)] pub struct GenericArg<'tcx> { ptr: NonZeroUsize, marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>, diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs index 011c2ceebb714..bba5394facbb6 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_query_system/src/query/caches.rs @@ -1,9 +1,11 @@ use crate::dep_graph::DepNodeIndex; use crate::query::plumbing::{QueryCacheStore, QueryLookup}; +use crate::query::HashStableKey; use rustc_arena::TypedArena; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sharded::Sharded; +use rustc_data_structures::stable_hasher::HashStableEq; use rustc_data_structures::sync::WorkerLocal; use std::default::Default; use std::fmt::Debug; @@ -24,7 +26,7 @@ pub trait QueryStorage { } pub trait QueryCache: QueryStorage + Sized { - type Key: Hash + Eq + Clone + Debug; + type Key: Hash + HashStableEq + Clone + Debug; type Sharded: Default; /// Checks if the query is already computed and in the cache. @@ -58,7 +60,7 @@ pub trait QueryCache: QueryStorage + Sized { pub struct DefaultCacheSelector; -impl CacheSelector for DefaultCacheSelector { +impl CacheSelector for DefaultCacheSelector { type Cache = DefaultCache; } @@ -70,7 +72,7 @@ impl Default for DefaultCache { } } -impl QueryStorage for DefaultCache { +impl QueryStorage for DefaultCache { type Value = V; type Stored = V; @@ -83,11 +85,11 @@ impl QueryStorage for DefaultCache { impl QueryCache for DefaultCache where - K: Eq + Hash + Clone + Debug, + K: HashStableEq + Hash + Clone + Debug, V: Clone + Debug, { type Key = K; - type Sharded = FxHashMap; + type Sharded = FxHashMap, (V, DepNodeIndex)>; #[inline(always)] fn lookup<'s, R, OnHit>( @@ -100,7 +102,8 @@ where OnHit: FnOnce(&V, DepNodeIndex) -> R, { let (lookup, lock) = state.get_lookup(key); - let result = lock.raw_entry().from_key_hashed_nocheck(lookup.key_hash, key); + let result = + lock.raw_entry().from_key_hashed_nocheck(lookup.key_hash, HashStableKey::from_ref(key)); if let Some((_, value)) = result { let hit_result = on_hit(&value.0, value.1); @@ -118,7 +121,7 @@ where value: V, index: DepNodeIndex, ) -> Self::Stored { - lock_sharded_storage.insert(key, (value.clone(), index)); + lock_sharded_storage.insert(HashStableKey(key), (value.clone(), index)); value } @@ -130,7 +133,7 @@ where let shards = shards.lock_shards(); for shard in shards.iter() { for (k, v) in shard.iter() { - f(k, &v.0, v.1); + f(&k.0, &v.0, v.1); } } } @@ -138,7 +141,7 @@ where pub struct ArenaCacheSelector<'tcx>(PhantomData<&'tcx ()>); -impl<'tcx, K: Eq + Hash, V: 'tcx> CacheSelector for ArenaCacheSelector<'tcx> { +impl<'tcx, K: HashStableEq + Hash, V: 'tcx> CacheSelector for ArenaCacheSelector<'tcx> { type Cache = ArenaCache<'tcx, K, V>; } @@ -153,7 +156,7 @@ impl<'tcx, K, V> Default for ArenaCache<'tcx, K, V> { } } -impl<'tcx, K: Eq + Hash, V: Debug + 'tcx> QueryStorage for ArenaCache<'tcx, K, V> { +impl<'tcx, K: HashStableEq + Hash, V: Debug + 'tcx> QueryStorage for ArenaCache<'tcx, K, V> { type Value = V; type Stored = &'tcx V; @@ -167,11 +170,11 @@ impl<'tcx, K: Eq + Hash, V: Debug + 'tcx> QueryStorage for ArenaCache<'tcx, K, V impl<'tcx, K, V: 'tcx> QueryCache for ArenaCache<'tcx, K, V> where - K: Eq + Hash + Clone + Debug, + K: HashStableEq + Hash + Clone + Debug, V: Debug, { type Key = K; - type Sharded = FxHashMap; + type Sharded = FxHashMap, &'tcx (V, DepNodeIndex)>; #[inline(always)] fn lookup<'s, R, OnHit>( @@ -184,7 +187,8 @@ where OnHit: FnOnce(&&'tcx V, DepNodeIndex) -> R, { let (lookup, lock) = state.get_lookup(key); - let result = lock.raw_entry().from_key_hashed_nocheck(lookup.key_hash, key); + let result = + lock.raw_entry().from_key_hashed_nocheck(lookup.key_hash, HashStableKey::from_ref(key)); if let Some((_, value)) = result { let hit_result = on_hit(&&value.0, value.1); @@ -204,7 +208,7 @@ where ) -> Self::Stored { let value = self.arena.alloc((value, index)); let value = unsafe { &*(value as *const _) }; - lock_sharded_storage.insert(key, value); + lock_sharded_storage.insert(HashStableKey(key), value); &value.0 } @@ -216,7 +220,7 @@ where let shards = shards.lock_shards(); for shard in shards.iter() { for (k, v) in shard.iter() { - f(k, &v.0, v.1); + f(&k.0, &v.0, v.1); } } } diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 77e1fd3f2ccbb..b0672ed666278 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -12,6 +12,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHasher}; #[cfg(parallel_compiler)] use rustc_data_structures::profiling::TimingGuard; use rustc_data_structures::sharded::{get_shard_index_by_hash, Sharded}; +use rustc_data_structures::stable_hasher::HashStableEq; use rustc_data_structures::sync::{Lock, LockGuard}; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::{DiagnosticBuilder, FatalError}; @@ -67,9 +68,27 @@ impl QueryCacheStore { } struct QueryStateShard { - active: FxHashMap, + active: FxHashMap, QueryResult>, } +#[derive(Copy, Clone, Hash)] +#[repr(transparent)] +pub struct HashStableKey(pub K); + +impl HashStableKey { + pub fn from_ref(val: &K) -> &HashStableKey { + unsafe { std::mem::transmute(val) } + } +} + +impl PartialEq for HashStableKey { + fn eq(&self, other: &Self) -> bool { + self.0.hash_stable_eq(&other.0) + } +} + +impl Eq for HashStableKey {} + impl Default for QueryStateShard { fn default() -> QueryStateShard { QueryStateShard { active: Default::default() } @@ -92,7 +111,7 @@ enum QueryResult { impl QueryState where - K: Eq + Hash + Clone + Debug, + K: Clone + Debug, { pub fn all_inactive(&self) -> bool { let shards = self.shards.lock_shards(); @@ -111,7 +130,7 @@ where for shard in shards.iter() { for (k, v) in shard.active.iter() { if let QueryResult::Started(ref job) = *v { - let query = make_query(tcx, k.clone()); + let query = make_query(tcx, k.0.clone()); jobs.insert(job.id, QueryJobInfo { query, job: job.clone() }); } } @@ -131,7 +150,7 @@ impl Default for QueryState { /// This will poison the relevant query if dropped. struct JobOwner<'tcx, K> where - K: Eq + Hash + Clone, + K: HashStableEq + Hash + Clone, { state: &'tcx QueryState, key: K, @@ -158,7 +177,7 @@ where impl<'tcx, K> JobOwner<'tcx, K> where - K: Eq + Hash + Clone, + K: HashStableEq + Hash + Clone, { /// Either gets a `JobOwner` corresponding the query, allowing us to /// start executing the query, or returns with the result of the query. @@ -183,13 +202,13 @@ where let mut state_lock = state.shards.get_shard_by_index(shard).lock(); let lock = &mut *state_lock; - match lock.active.entry(key) { + match lock.active.entry(HashStableKey(key)) { Entry::Vacant(entry) => { let id = tcx.next_job_id(); let job = tcx.current_query_job(); let job = QueryJob::new(id, span, job); - let key = entry.key().clone(); + let key = entry.key().0.clone(); entry.insert(QueryResult::Started(job)); let owner = JobOwner { state, id, key }; @@ -256,11 +275,11 @@ where mem::forget(self); let (job, result) = { - let key_hash = hash_for_shard(&key); + let key_hash = hash_for_shard(HashStableKey::from_ref(&key)); let shard = get_shard_index_by_hash(key_hash); let job = { let mut lock = state.shards.get_shard_by_index(shard).lock(); - match lock.active.remove(&key).unwrap() { + match lock.active.remove(HashStableKey::from_ref(&key)).unwrap() { QueryResult::Started(job) => job, QueryResult::Poisoned => panic!(), } @@ -279,21 +298,21 @@ where impl<'tcx, K> Drop for JobOwner<'tcx, K> where - K: Eq + Hash + Clone, + K: HashStableEq + Hash + Clone, { #[inline(never)] #[cold] fn drop(&mut self) { // Poison the query so jobs waiting on it panic. let state = self.state; - let shard = state.shards.get_shard_by_value(&self.key); + let shard = state.shards.get_shard_by_value(HashStableKey::from_ref(&self.key)); let job = { let mut shard = shard.lock(); - let job = match shard.active.remove(&self.key).unwrap() { + let job = match shard.active.remove(HashStableKey::from_ref(&self.key)).unwrap() { QueryResult::Started(job) => job, QueryResult::Poisoned => panic!(), }; - shard.active.insert(self.key.clone(), QueryResult::Poisoned); + shard.active.insert(HashStableKey(self.key.clone()), QueryResult::Poisoned); job }; // Also signal the completion of the job, so waiters @@ -312,7 +331,7 @@ pub(crate) struct CycleError { /// The result of `try_start`. enum TryGetJob<'tcx, K> where - K: Eq + Hash + Clone, + K: HashStableEq + Hash + Clone, { /// The query is not yet started. Contains a guard to the cache eventually used to start it. NotYetStarted(JobOwner<'tcx, K>), diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 68e7cc3dc9874..eaf35aec7c440 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -397,7 +397,7 @@ pub enum TrimmedDefPaths { /// *Do not* switch `BTreeMap` out for an unsorted container type! That would break /// dependency tracking for command-line arguments. Also only hash keys, since tracking /// should only depend on the output types, not the paths they're written to. -#[derive(Clone, Debug, Hash)] +#[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct OutputTypes(BTreeMap>); impl OutputTypes { @@ -629,7 +629,7 @@ impl Input { } } -#[derive(Clone, Hash, Debug)] +#[derive(Clone, Hash, Debug, PartialEq, Eq)] pub struct OutputFilenames { pub out_directory: PathBuf, filestem: String, diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 281fc887633d9..1080a02e2af15 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -65,6 +65,7 @@ pub enum LinkagePreference { } #[derive(Debug, Encodable, Decodable, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct NativeLib { pub kind: NativeLibKind, pub name: Option, diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 147c1f9e04339..68a69d2002173 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -10,6 +10,7 @@ use std::fmt; use std::hash::{Hash, Hasher}; rustc_index::newtype_index! { + #[derive(HashStableEq)] pub struct CrateNum { ENCODABLE = custom DEBUG_FORMAT = "crate{}" @@ -192,6 +193,7 @@ rustc_index::newtype_index! { /// A DefIndex is an index into the hir-map for a crate, identifying a /// particular definition. It should really be considered an interned /// shorthand for a particular DefPath. + #[derive(HashStableEq)] pub struct DefIndex { ENCODABLE = custom // (only encodable in metadata) @@ -218,7 +220,7 @@ impl Decodable for DefIndex { /// index and a def index. /// /// You can create a `DefId` from a `LocalDefId` using `local_def_id.to_def_id()`. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Copy)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Copy, HashStableEq)] // On below-64 bit systems we can simply use the derived `Hash` impl #[cfg_attr(not(target_pointer_width = "64"), derive(Hash))] #[repr(C)] @@ -327,7 +329,7 @@ rustc_data_structures::define_id_collections!(DefIdMap, DefIdSet, DefId); /// few cases where we know that only `DefId`s from the local crate are expected; /// a `DefId` from a different crate would signify a bug somewhere. This /// is when `LocalDefId` comes in handy. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStableEq)] pub struct LocalDefId { pub local_def_index: DefIndex, } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 8265eb23c3db4..929940188bb47 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -33,7 +33,7 @@ use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::HashingControls; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, HashStableEq, StableHasher}; use rustc_data_structures::sync::{Lock, Lrc}; use rustc_data_structures::unhash::UnhashMap; use rustc_index::vec::IndexVec; @@ -74,6 +74,12 @@ pub struct ExpnId { pub local_id: ExpnIndex, } +impl HashStableEq for ExpnId { + fn hash_stable_eq(&self, other: &Self) -> bool { + self == other + } +} + impl fmt::Debug for ExpnId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Generate crate_::{{expn_}}. diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index 61e4074a7c80b..cef7891cb44ba 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -60,7 +60,7 @@ use rustc_data_structures::fx::FxIndexSet; /// the dependency to the parent definition's span. This is performed /// using the callback `SPAN_TRACK` to access the query engine. /// -#[derive(Clone, Copy, Eq, PartialEq, Hash)] +#[derive(Clone, Copy, Eq, PartialEq, Hash, HashStableEq)] // FIXME(@lcnr): Enable this attribute once the bootstrap // compiler knows of `rustc_pass_by_value`. // diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 33140911f91c6..c4fb8d176da50 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -4,7 +4,9 @@ use rustc_arena::DroplessArena; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_data_structures::stable_hasher::{ + HashStable, HashStableEq, StableHasher, ToStableHashKey, +}; use rustc_data_structures::sync::Lock; use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -1710,6 +1712,12 @@ impl fmt::Display for MacroRulesNormalizedIdent { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Symbol(SymbolIndex); +impl HashStableEq for Symbol { + fn hash_stable_eq(&self, other: &Self) -> bool { + self == other + } +} + rustc_index::newtype_index! { struct SymbolIndex { .. } } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 34324a582977d..1927e54c94c3c 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -462,6 +462,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { /// Information about how to pass an argument to, /// or return a value from, a function, under some ABI. #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct ArgAbi<'a, Ty> { pub layout: TyAndLayout<'a, Ty>, @@ -608,6 +609,7 @@ pub enum Conv { /// I will do my best to describe this structure, but these /// comments are reverse-engineered and may be inaccurate. -NDM #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct FnAbi<'a, Ty> { /// The LLVM types of each argument. pub args: Vec>, diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 7f1fd28b30df8..bc601634aceb1 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -1027,6 +1027,7 @@ rustc_index::newtype_index! { } #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum Variants { /// Single enum variants, structs/tuples, unions, and all non-ADTs. Single { index: VariantIdx }, @@ -1046,6 +1047,7 @@ pub enum Variants { } #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub enum TagEncoding { /// The tag directly stores the discriminant, but possibly with a smaller layout /// (so converting the tag to the discriminant can require sign extension). @@ -1150,6 +1152,7 @@ impl Niche { } #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct Layout { /// Says where the fields are located within the layout. pub fields: FieldsShape, @@ -1204,6 +1207,7 @@ impl Layout { /// layouts for which Rust types do not exist, such as enum variants /// or synthetic fields of enums (i.e., discriminants) and fat pointers. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable_Generic)] +#[stable_hasher(no_hash_stable_eq)] pub struct TyAndLayout<'a, Ty> { pub ty: Ty, pub layout: &'a Layout, diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index e26f0033156bc..edc2fc1ec760a 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -150,6 +150,7 @@ rustc_index::newtype_index! { /// is the outer fn. /// /// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index + #[derive(HashStableEq)] pub struct DebruijnIndex { DEBUG_FORMAT = "DebruijnIndex({})", const INNERMOST = 0, @@ -215,7 +216,7 @@ impl DebruijnIndex { } } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, HashStableEq)] #[derive(Encodable, Decodable)] pub enum IntTy { Isize, @@ -262,7 +263,7 @@ impl IntTy { } } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug, HashStableEq)] #[derive(Encodable, Decodable)] pub enum UintTy { Usize, @@ -309,7 +310,7 @@ impl UintTy { } } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, HashStableEq)] #[derive(Encodable, Decodable)] pub enum FloatTy { F32, @@ -343,19 +344,20 @@ pub struct FloatVarValue(pub FloatTy); rustc_index::newtype_index! { /// A **ty**pe **v**ariable **ID**. + #[derive(HashStableEq)] pub struct TyVid { DEBUG_FORMAT = "_#{}t" } } /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, HashStableEq)] pub struct IntVid { pub index: u32, } /// An **float**ing-point (`f32` or `f64`) type **v**ariable **ID**. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, HashStableEq)] pub struct FloatVid { pub index: u32, } @@ -365,7 +367,7 @@ pub struct FloatVid { /// E.g., if we have an empty array (`[]`), then we create a fresh /// type variable for the element type since we won't know until it's /// used what the element type is supposed to be. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, HashStableEq)] pub enum InferTy { /// A type variable. TyVar(TyVid), @@ -447,7 +449,7 @@ impl UnifyKey for FloatVid { } } -#[derive(Copy, Clone, PartialEq, Decodable, Encodable, Hash)] +#[derive(Copy, Clone, PartialEq, Decodable, Encodable, Hash, HashStableEq)] pub enum Variance { Covariant, // T <: T iff A <: B -- e.g., function return type Invariant, // T <: T iff B == A -- e.g., type of mutable cell