diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 34303cbbc9a18..7e713a49a8cfa 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -59,9 +59,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro /// instead of implementing everything in `rustc_middle`. -pub trait HashStableContext: - rustc_type_ir::HashStableContext + rustc_span::HashStableContext -{ +pub trait HashStableContext: rustc_span::HashStableContext { fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher); } diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs index 6d23b9ac99d24..564e3a1edfac0 100644 --- a/compiler/rustc_macros/src/hash_stable.rs +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -64,6 +64,50 @@ pub(crate) fn hash_stable_generic_derive( ) } +pub(crate) fn hash_stable_no_context_derive( + mut s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { + let generic: syn::GenericParam = parse_quote!(__CTX); + s.add_bounds(synstructure::AddBounds::Fields); + s.add_impl_generic(generic); + let body = s.each(|bi| { + let attrs = parse_attributes(bi.ast()); + if attrs.ignore { + quote! {} + } else if let Some(project) = attrs.project { + quote! { + (&#bi.#project).hash_stable(__hcx, __hasher); + } + } else { + quote! { + #bi.hash_stable(__hcx, __hasher); + } + } + }); + + let discriminant = match s.ast().data { + syn::Data::Enum(_) => quote! { + ::std::mem::discriminant(self).hash_stable(__hcx, __hasher); + }, + syn::Data::Struct(_) => quote! {}, + syn::Data::Union(_) => panic!("cannot derive on union"), + }; + + s.bound_impl( + quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>), + quote! { + #[inline] + fn hash_stable( + &self, + __hcx: &mut __CTX, + __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { + #discriminant + match *self { #body } + } + }, + ) +} + pub(crate) fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { let generic: syn::GenericParam = parse_quote!('__ctx); s.add_bounds(synstructure::AddBounds::Generics); diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index a66666360324e..5aaacaa7b6985 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -70,6 +70,13 @@ decl_derive!( [HashStable_Generic, attributes(stable_hasher)] => hash_stable::hash_stable_generic_derive ); +decl_derive!( + [HashStable_NoContext] => + /// `HashStable` implementation that has no `HashStableContext` bound and + /// which adds `where` bounds for `HashStable` based off of fields and not + /// generics. This is suitable for use in crates like `rustc_type_ir`. + hash_stable::hash_stable_no_context_derive +); decl_derive!([Decodable] => serialize::decodable_derive); decl_derive!([Encodable] => serialize::encodable_derive); diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs index b2177be0e368c..81a7eb604f5a8 100644 --- a/compiler/rustc_query_system/src/ich/impls_syntax.rs +++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs @@ -123,5 +123,3 @@ impl<'tcx> HashStable> for rustc_feature::Features { }); } } - -impl<'ctx> rustc_type_ir::HashStableContext for StableHashingContext<'ctx> {} diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index ace9eade7f69b..08a52865fa67b 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -2,18 +2,16 @@ use std::fmt; use std::hash::Hash; use std::ops::ControlFlow; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; - use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; -use crate::{HashStableContext, Interner, UniverseIndex}; +use crate::{Interner, UniverseIndex}; /// A "canonicalized" type `V` is one where all free inference /// variables have been rewritten to "canonical vars". These are /// numbered starting from 0 in order of first appearance. #[derive(derivative::Derivative)] #[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))] -#[derive(TyEncodable, TyDecodable)] +#[derive(TyEncodable, TyDecodable, HashStable_NoContext)] pub struct Canonical { pub value: V, pub max_universe: UniverseIndex, @@ -60,17 +58,6 @@ impl Canonical { } } -impl> HashStable for Canonical -where - I::CanonicalVars: HashStable, -{ - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - self.value.hash_stable(hcx, hasher); - self.max_universe.hash_stable(hcx, hasher); - self.variables.hash_stable(hcx, hasher); - } -} - impl Eq for Canonical {} impl PartialEq for Canonical { diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 33782b13ca8f5..7b2412153b2c3 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -1,8 +1,6 @@ -use rustc_data_structures::stable_hasher::HashStable; -use rustc_data_structures::stable_hasher::StableHasher; use std::fmt; -use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx}; +use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx}; use self::ConstKind::*; @@ -16,7 +14,7 @@ use self::ConstKind::*; Ord = "feature_allow_slow_enum", Hash(bound = "") )] -#[derive(TyEncodable, TyDecodable)] +#[derive(TyEncodable, TyDecodable, HashStable_NoContext)] pub enum ConstKind { /// A const generic parameter. Param(I::ParamConst), @@ -47,48 +45,6 @@ pub enum ConstKind { Expr(I::ExprConst), } -const fn const_kind_discriminant(value: &ConstKind) -> usize { - match value { - Param(_) => 0, - Infer(_) => 1, - Bound(_, _) => 2, - Placeholder(_) => 3, - Unevaluated(_) => 4, - Value(_) => 5, - Error(_) => 6, - Expr(_) => 7, - } -} - -impl HashStable for ConstKind -where - I::ParamConst: HashStable, - I::InferConst: HashStable, - I::BoundConst: HashStable, - I::PlaceholderConst: HashStable, - I::AliasConst: HashStable, - I::ValueConst: HashStable, - I::ErrorGuaranteed: HashStable, - I::ExprConst: HashStable, -{ - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - const_kind_discriminant(self).hash_stable(hcx, hasher); - match self { - Param(p) => p.hash_stable(hcx, hasher), - Infer(i) => i.hash_stable(hcx, hasher), - Bound(d, b) => { - d.hash_stable(hcx, hasher); - b.hash_stable(hcx, hasher); - } - Placeholder(p) => p.hash_stable(hcx, hasher), - Unevaluated(u) => u.hash_stable(hcx, hasher), - Value(v) => v.hash_stable(hcx, hasher), - Error(e) => e.hash_stable(hcx, hasher), - Expr(e) => e.hash_stable(hcx, hasher), - } - } -} - impl PartialEq for ConstKind { fn eq(&self, other: &Self) -> bool { match (self, other) { diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index e8785fff2efcd..658ddbceb4539 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -47,9 +47,6 @@ pub use region_kind::*; pub use ty_info::*; pub use ty_kind::*; -/// Needed so we can use #[derive(HashStable_Generic)] -pub trait HashStableContext {} - rustc_index::newtype_index! { /// A [De Bruijn index][dbi] is a standard means of representing /// regions (and perhaps later types) in a higher-ranked setting. In @@ -90,7 +87,7 @@ rustc_index::newtype_index! { /// is the outer fn. /// /// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index - #[derive(HashStable_Generic)] + #[derive(HashStable_NoContext)] #[debug_format = "DebruijnIndex({})"] pub struct DebruijnIndex { const INNERMOST = 0; @@ -173,7 +170,7 @@ pub fn debug_bound_var( } } -#[derive(Copy, Clone, PartialEq, Eq, Decodable, Encodable, Hash, HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Eq, Decodable, Encodable, Hash, HashStable_NoContext)] #[rustc_pass_by_value] pub enum Variance { Covariant, // T <: T iff A <: B -- e.g., function return type @@ -289,7 +286,7 @@ rustc_index::newtype_index! { /// declared, but a type name in a non-zero universe is a placeholder /// type -- an idealized representative of "types in general" that we /// use for checking generic functions. - #[derive(HashStable_Generic)] + #[derive(HashStable_NoContext)] #[debug_format = "U{}"] pub struct UniverseIndex {} } diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 48662d4264235..fb86d31f1a3ff 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -1,16 +1,15 @@ -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use std::fmt; use std::ops::ControlFlow; use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; -use crate::{HashStableContext, Interner}; +use crate::Interner; /// A clause is something that can appear in where bounds or be inferred /// by implied bounds. #[derive(derivative::Derivative)] #[derivative(Clone(bound = ""), Hash(bound = ""))] -#[derive(TyEncodable, TyDecodable)] +#[derive(TyEncodable, TyDecodable, HashStable_NoContext)] pub enum ClauseKind { /// Corresponds to `where Foo: Bar`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` @@ -67,45 +66,6 @@ impl PartialEq for ClauseKind { impl Eq for ClauseKind {} -fn clause_kind_discriminant(value: &ClauseKind) -> usize { - match value { - ClauseKind::Trait(_) => 0, - ClauseKind::RegionOutlives(_) => 1, - ClauseKind::TypeOutlives(_) => 2, - ClauseKind::Projection(_) => 3, - ClauseKind::ConstArgHasType(_, _) => 4, - ClauseKind::WellFormed(_) => 5, - ClauseKind::ConstEvaluatable(_) => 6, - } -} - -impl HashStable for ClauseKind -where - I::Ty: HashStable, - I::Const: HashStable, - I::GenericArg: HashStable, - I::TraitPredicate: HashStable, - I::ProjectionPredicate: HashStable, - I::TypeOutlivesPredicate: HashStable, - I::RegionOutlivesPredicate: HashStable, -{ - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - clause_kind_discriminant(self).hash_stable(hcx, hasher); - match self { - ClauseKind::Trait(p) => p.hash_stable(hcx, hasher), - ClauseKind::RegionOutlives(p) => p.hash_stable(hcx, hasher), - ClauseKind::TypeOutlives(p) => p.hash_stable(hcx, hasher), - ClauseKind::Projection(p) => p.hash_stable(hcx, hasher), - ClauseKind::ConstArgHasType(c, t) => { - c.hash_stable(hcx, hasher); - t.hash_stable(hcx, hasher); - } - ClauseKind::WellFormed(t) => t.hash_stable(hcx, hasher), - ClauseKind::ConstEvaluatable(c) => c.hash_stable(hcx, hasher), - } - } -} - impl TypeFoldable for ClauseKind where I::Ty: TypeFoldable, @@ -161,7 +121,7 @@ where #[derive(derivative::Derivative)] #[derivative(Clone(bound = ""), Hash(bound = ""))] -#[derive(TyEncodable, TyDecodable)] +#[derive(TyEncodable, TyDecodable, HashStable_NoContext)] pub enum PredicateKind { /// Prove a clause Clause(ClauseKind), @@ -239,56 +199,6 @@ impl PartialEq for PredicateKind { impl Eq for PredicateKind {} -fn predicate_kind_discriminant(value: &PredicateKind) -> usize { - match value { - PredicateKind::Clause(_) => 0, - PredicateKind::ObjectSafe(_) => 1, - PredicateKind::ClosureKind(_, _, _) => 2, - PredicateKind::Subtype(_) => 3, - PredicateKind::Coerce(_) => 4, - PredicateKind::ConstEquate(_, _) => 5, - PredicateKind::Ambiguous => 6, - PredicateKind::AliasRelate(_, _, _) => 7, - } -} - -impl HashStable for PredicateKind -where - I::DefId: HashStable, - I::Const: HashStable, - I::GenericArgs: HashStable, - I::Term: HashStable, - I::CoercePredicate: HashStable, - I::SubtypePredicate: HashStable, - I::ClosureKind: HashStable, - ClauseKind: HashStable, -{ - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - predicate_kind_discriminant(self).hash_stable(hcx, hasher); - match self { - PredicateKind::Clause(p) => p.hash_stable(hcx, hasher), - PredicateKind::ObjectSafe(d) => d.hash_stable(hcx, hasher), - PredicateKind::ClosureKind(d, g, k) => { - d.hash_stable(hcx, hasher); - g.hash_stable(hcx, hasher); - k.hash_stable(hcx, hasher); - } - PredicateKind::Subtype(p) => p.hash_stable(hcx, hasher), - PredicateKind::Coerce(p) => p.hash_stable(hcx, hasher), - PredicateKind::ConstEquate(c1, c2) => { - c1.hash_stable(hcx, hasher); - c2.hash_stable(hcx, hasher); - } - PredicateKind::Ambiguous => {} - PredicateKind::AliasRelate(t1, t2, r) => { - t1.hash_stable(hcx, hasher); - t2.hash_stable(hcx, hasher); - r.hash_stable(hcx, hasher); - } - } - } -} - impl TypeFoldable for PredicateKind where I::DefId: TypeFoldable, @@ -361,7 +271,7 @@ where } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] -#[derive(HashStable_Generic, Encodable, Decodable)] +#[derive(HashStable_NoContext, Encodable, Decodable)] pub enum AliasRelationDirection { Equate, Subtype, diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 5d3ce49bc8f76..e1657aaa0fbef 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -1,8 +1,7 @@ -use rustc_data_structures::stable_hasher::HashStable; -use rustc_data_structures::stable_hasher::StableHasher; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use std::fmt; -use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx}; +use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx}; use self::RegionKind::*; @@ -262,7 +261,7 @@ impl fmt::Debug for RegionKind { } // This is not a derived impl because a derive would require `I: HashStable` -impl HashStable for RegionKind +impl HashStable for RegionKind where I::EarlyParamRegion: HashStable, I::BoundRegion: HashStable, diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 09a9a332269ef..3442e9d4756c9 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -5,7 +5,6 @@ use rustc_data_structures::unify::{EqUnifyValue, UnifyKey}; use std::fmt; use std::mem::discriminant; -use crate::HashStableContext; use crate::Interner; use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx}; @@ -14,7 +13,7 @@ use self::TyKind::*; /// The movability of a coroutine / closure literal: /// whether a coroutine contains self-references, causing it to be `!Unpin`. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)] -#[derive(HashStable_Generic)] +#[derive(HashStable_NoContext)] pub enum Movability { /// May contain self-references, `!Unpin`. Static, @@ -23,7 +22,7 @@ pub enum Movability { } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] -#[derive(HashStable_Generic, Encodable, Decodable)] +#[derive(HashStable_NoContext, Encodable, Decodable)] pub enum Mutability { // N.B. Order is deliberate, so that Not < Mut Not, @@ -75,7 +74,7 @@ impl Mutability { /// Specifies how a trait object is represented. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[derive(Encodable, Decodable, HashStable_NoContext)] pub enum DynKind { /// An unsized `dyn Trait` object Dyn, @@ -89,7 +88,7 @@ pub enum DynKind { } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[derive(Encodable, Decodable, HashStable_NoContext)] pub enum AliasKind { /// A projection `::AssocType`. /// Can get normalized away if monomorphic enough. @@ -119,7 +118,7 @@ pub enum AliasKind { Ord = "feature_allow_slow_enum", Hash(bound = "") )] -#[derive(TyEncodable, TyDecodable)] +#[derive(TyEncodable, TyDecodable, HashStable_NoContext)] pub enum TyKind { /// The primitive boolean type. Written as `bool`. Bool, @@ -470,120 +469,8 @@ impl fmt::Debug for TyKind { } } -// This is not a derived impl because a derive would require `I: HashStable` -#[allow(rustc::usage_of_ty_tykind)] -impl HashStable for TyKind -where - I::AdtDef: HashStable, - I::DefId: HashStable, - I::GenericArgs: HashStable, - I::Ty: HashStable, - I::Const: HashStable, - I::TypeAndMut: HashStable, - I::PolyFnSig: HashStable, - I::BoundExistentialPredicates: HashStable, - I::Region: HashStable, - I::Tys: HashStable, - I::AliasTy: HashStable, - I::BoundTy: HashStable, - I::ParamTy: HashStable, - I::PlaceholderTy: HashStable, - I::InferTy: HashStable, - I::ErrorGuaranteed: HashStable, -{ - #[inline] - fn hash_stable(&self, __hcx: &mut CTX, __hasher: &mut StableHasher) { - std::mem::discriminant(self).hash_stable(__hcx, __hasher); - match self { - Bool => {} - Char => {} - Int(i) => { - i.hash_stable(__hcx, __hasher); - } - Uint(u) => { - u.hash_stable(__hcx, __hasher); - } - Float(f) => { - f.hash_stable(__hcx, __hasher); - } - Adt(adt, args) => { - adt.hash_stable(__hcx, __hasher); - args.hash_stable(__hcx, __hasher); - } - Foreign(def_id) => { - def_id.hash_stable(__hcx, __hasher); - } - Str => {} - Array(t, c) => { - t.hash_stable(__hcx, __hasher); - c.hash_stable(__hcx, __hasher); - } - Slice(t) => { - t.hash_stable(__hcx, __hasher); - } - RawPtr(tam) => { - tam.hash_stable(__hcx, __hasher); - } - Ref(r, t, m) => { - r.hash_stable(__hcx, __hasher); - t.hash_stable(__hcx, __hasher); - m.hash_stable(__hcx, __hasher); - } - FnDef(def_id, args) => { - def_id.hash_stable(__hcx, __hasher); - args.hash_stable(__hcx, __hasher); - } - FnPtr(polyfnsig) => { - polyfnsig.hash_stable(__hcx, __hasher); - } - Dynamic(l, r, repr) => { - l.hash_stable(__hcx, __hasher); - r.hash_stable(__hcx, __hasher); - repr.hash_stable(__hcx, __hasher); - } - Closure(def_id, args) => { - def_id.hash_stable(__hcx, __hasher); - args.hash_stable(__hcx, __hasher); - } - Coroutine(def_id, args, m) => { - def_id.hash_stable(__hcx, __hasher); - args.hash_stable(__hcx, __hasher); - m.hash_stable(__hcx, __hasher); - } - CoroutineWitness(def_id, args) => { - def_id.hash_stable(__hcx, __hasher); - args.hash_stable(__hcx, __hasher); - } - Never => {} - Tuple(args) => { - args.hash_stable(__hcx, __hasher); - } - Alias(k, p) => { - k.hash_stable(__hcx, __hasher); - p.hash_stable(__hcx, __hasher); - } - Param(p) => { - p.hash_stable(__hcx, __hasher); - } - Bound(d, b) => { - d.hash_stable(__hcx, __hasher); - b.hash_stable(__hcx, __hasher); - } - Placeholder(p) => { - p.hash_stable(__hcx, __hasher); - } - Infer(i) => { - i.hash_stable(__hcx, __hasher); - } - Error(d) => { - d.hash_stable(__hcx, __hasher); - } - } - } -} - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[derive(Encodable, Decodable, HashStable_NoContext)] pub enum IntTy { Isize, I8, @@ -641,7 +528,7 @@ impl IntTy { } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[derive(Encodable, Decodable, HashStable_NoContext)] pub enum UintTy { Usize, U8, @@ -699,7 +586,7 @@ impl UintTy { } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[derive(Encodable, Decodable, HashStable_NoContext)] pub enum FloatTy { F32, F64, @@ -753,7 +640,8 @@ rustc_index::newtype_index! { /// 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)] +#[derive(Encodable, Decodable)] pub enum InferTy { /// A type variable. TyVar(TyVid),