From 426bc70ad661e6edd66949f3d938c0c07571dbc5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 4 Nov 2023 17:02:54 +0000 Subject: [PATCH 1/2] Add HashStable_NoContext to simplify HashStable implementations in rustc_type_ir --- compiler/rustc_ast/src/lib.rs | 4 +- compiler/rustc_macros/src/hash_stable.rs | 44 ++++++ compiler/rustc_macros/src/lib.rs | 7 + .../src/ich/impls_syntax.rs | 2 - compiler/rustc_type_ir/src/canonical.rs | 18 +-- compiler/rustc_type_ir/src/const_kind.rs | 45 +----- compiler/rustc_type_ir/src/lib.rs | 9 +- compiler/rustc_type_ir/src/predicate_kind.rs | 101 +------------- compiler/rustc_type_ir/src/region_kind.rs | 2 +- compiler/rustc_type_ir/src/ty_kind.rs | 128 ++---------------- 10 files changed, 69 insertions(+), 291 deletions(-) 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 2775bd5f6290a..f558b74be9a99 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -48,6 +48,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 a0e4b4ecbfcaa..9f170c5b4db61 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -2,9 +2,6 @@ use std::fmt; use std::hash::Hash; use std::ops::ControlFlow; -#[cfg(feature = "nightly")] -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; - use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; use crate::{Interner, UniverseIndex}; @@ -14,7 +11,7 @@ use crate::{Interner, UniverseIndex}; /// numbered starting from 0 in order of first appearance. #[derive(derivative::Derivative)] #[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub struct Canonical { pub value: V, pub max_universe: UniverseIndex, @@ -61,19 +58,6 @@ impl Canonical { } } -#[cfg(feature = "nightly")] -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 1cdd51d68dc68..a5f90421de5f7 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -16,7 +16,7 @@ use self::ConstKind::*; Ord = "feature_allow_slow_enum", Hash(bound = "") )] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum ConstKind { /// A const generic parameter. Param(I::ParamConst), @@ -47,49 +47,6 @@ pub enum ConstKind { Expr(I::ExprConst), } -#[cfg(feature = "nightly")] -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, - } -} - -#[cfg(feature = "nightly")] -impl HashStable for ConstKind -where - I::ParamConst: 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 ba558aa341881..acea7aa46f6f5 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -51,9 +51,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 @@ -94,7 +91,7 @@ rustc_index::newtype_index! { /// is the outer fn. /// /// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index - #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] + #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] #[debug_format = "DebruijnIndex({})"] #[gate_rustc_only] pub struct DebruijnIndex { @@ -179,7 +176,7 @@ pub fn debug_bound_var( } #[derive(Copy, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "nightly", derive(Decodable, Encodable, Hash, HashStable_Generic))] +#[cfg_attr(feature = "nightly", derive(Decodable, Encodable, Hash, HashStable_NoContext))] #[cfg_attr(feature = "nightly", rustc_pass_by_value)] pub enum Variance { Covariant, // T <: T iff A <: B -- e.g., function return type @@ -295,7 +292,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. - #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] + #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] #[debug_format = "U{}"] #[gate_rustc_only] pub struct UniverseIndex {} diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index c2ba6afc8d011..da041ab1f355f 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -1,5 +1,3 @@ -#[cfg(feature = "nightly")] -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use std::fmt; use std::ops::ControlFlow; @@ -11,7 +9,7 @@ use crate::Interner; /// by implied bounds. #[derive(derivative::Derivative)] #[derivative(Clone(bound = ""), Hash(bound = ""))] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] +#[cfg_attr(feature = "nightly", 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` @@ -68,47 +66,6 @@ impl PartialEq for ClauseKind { impl Eq for ClauseKind {} -#[cfg(feature = "nightly")] -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, - } -} - -#[cfg(feature = "nightly")] -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, @@ -164,7 +121,7 @@ where #[derive(derivative::Derivative)] #[derivative(Clone(bound = ""), Hash(bound = ""))] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum PredicateKind { /// Prove a clause Clause(ClauseKind), @@ -242,58 +199,6 @@ impl PartialEq for PredicateKind { impl Eq for PredicateKind {} -#[cfg(feature = "nightly")] -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, - } -} - -#[cfg(feature = "nightly")] -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, @@ -366,7 +271,7 @@ where } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] -#[cfg_attr(feature = "nightly", derive(HashStable_Generic, Encodable, Decodable))] +#[cfg_attr(feature = "nightly", 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 ddd10db1c6c7a..4157d49287c20 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -263,7 +263,7 @@ impl fmt::Debug for RegionKind { #[cfg(feature = "nightly")] // 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 53446c41f31c5..494eeaf3dc881 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -14,7 +14,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, Debug, Copy)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum Movability { /// May contain self-references, `!Unpin`. Static, @@ -23,7 +23,7 @@ pub enum Movability { } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum Mutability { // N.B. Order is deliberate, so that Not < Mut Not, @@ -75,7 +75,7 @@ impl Mutability { /// Specifies how a trait object is represented. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum DynKind { /// An unsized `dyn Trait` object Dyn, @@ -89,7 +89,7 @@ pub enum DynKind { } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum AliasKind { /// A projection `::AssocType`. /// Can get normalized away if monomorphic enough. @@ -119,7 +119,7 @@ pub enum AliasKind { Ord = "feature_allow_slow_enum", Hash(bound = "") )] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum TyKind { /// The primitive boolean type. Written as `bool`. Bool, @@ -472,120 +472,8 @@ impl fmt::Debug for TyKind { } } -// This is not a derived impl because a derive would require `I: HashStable` -#[cfg(feature = "nightly")] -#[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::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)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum IntTy { Isize, I8, @@ -643,7 +531,7 @@ impl IntTy { } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum UintTy { Usize, U8, @@ -701,7 +589,7 @@ impl UintTy { } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum FloatTy { F32, F64, From c9143ea1d9bad9871e77476f523da9d013357158 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 19 Nov 2023 23:25:25 +0000 Subject: [PATCH 2/2] Unify HashStable implementations --- compiler/rustc_macros/src/hash_stable.rs | 113 ++++++++++------------- 1 file changed, 49 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs index 564e3a1edfac0..2893937fc4a35 100644 --- a/compiler/rustc_macros/src/hash_stable.rs +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -38,95 +38,80 @@ fn parse_attributes(field: &syn::Field) -> Attributes { attrs } +pub(crate) fn hash_stable_derive(s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { + hash_stable_derive_with_mode(s, HashStableMode::Normal) +} + pub(crate) fn hash_stable_generic_derive( - mut s: synstructure::Structure<'_>, + s: synstructure::Structure<'_>, ) -> proc_macro2::TokenStream { - let generic: syn::GenericParam = parse_quote!(__CTX); - s.add_bounds(synstructure::AddBounds::Generics); - s.add_impl_generic(generic); - s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext }); + hash_stable_derive_with_mode(s, HashStableMode::Generic) +} - let discriminant = hash_stable_discriminant(&mut s); - let body = hash_stable_body(&mut s); +pub(crate) fn hash_stable_no_context_derive( + s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { + hash_stable_derive_with_mode(s, HashStableMode::NoContext) +} - 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 } - } - }, - ) +enum HashStableMode { + // Use the query-system aware stable hashing context. + Normal, + // Emit a generic implementation that uses a crate-local `StableHashingContext` + // trait, when the crate is upstream of `rustc_middle`. + Generic, + // Emit a hash-stable implementation that takes no context, + // and emits per-field where clauses for (almost-)perfect derives. + NoContext, } -pub(crate) fn hash_stable_no_context_derive( +fn hash_stable_derive_with_mode( mut s: synstructure::Structure<'_>, + mode: HashStableMode, ) -> 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"), + let generic: syn::GenericParam = match mode { + HashStableMode::Normal => parse_quote!('__ctx), + HashStableMode::Generic | HashStableMode::NoContext => parse_quote!(__CTX), }; - 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 } - } - }, - ) -} + // no_context impl is able to derive by-field, which is closer to a perfect derive. + s.add_bounds(match mode { + HashStableMode::Normal | HashStableMode::Generic => synstructure::AddBounds::Generics, + HashStableMode::NoContext => synstructure::AddBounds::Fields, + }); + + // For generic impl, add `where __CTX: HashStableContext`. + match mode { + HashStableMode::Normal => {} + HashStableMode::Generic => { + s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext }); + } + HashStableMode::NoContext => {} + } -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); s.add_impl_generic(generic); let discriminant = hash_stable_discriminant(&mut s); let body = hash_stable_body(&mut s); + let context: syn::Type = match mode { + HashStableMode::Normal => { + parse_quote!(::rustc_query_system::ich::StableHashingContext<'__ctx>) + } + HashStableMode::Generic | HashStableMode::NoContext => parse_quote!(__CTX), + }; + s.bound_impl( quote!( ::rustc_data_structures::stable_hasher::HashStable< - ::rustc_query_system::ich::StableHashingContext<'__ctx>, + #context > ), quote! { #[inline] fn hash_stable( &self, - __hcx: &mut ::rustc_query_system::ich::StableHashingContext<'__ctx>, + __hcx: &mut #context, __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { #discriminant match *self { #body }