Auto merge of #117580 - compiler-errors:hash-stable-simplify-rustc_type_ir, r=jackh726

Add `HashStable_NoContext` to simplify `HashStable` implementations in `rustc_type_ir`

adds `derive(HashStable_NoContext)` which is a derived `HashStable` implementation that has no `HashStableContext` bound, and which adds `where` bounds for `HashStable` based off of *fields* and not generics.

This means we can `derive(HashStable_NoContext)` in more places in `rustc_type_ir` rather than having to hand-roll implementations.
This commit is contained in:
bors 2023-11-21 11:13:15 +00:00
commit 7bd385dc37
10 changed files with 83 additions and 320 deletions

View File

@ -59,9 +59,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
/// Requirements for a `StableHashingContext` to be used in this crate. /// Requirements for a `StableHashingContext` to be used in this crate.
/// This is a hack to allow using the `HashStable_Generic` derive macro /// This is a hack to allow using the `HashStable_Generic` derive macro
/// instead of implementing everything in `rustc_middle`. /// instead of implementing everything in `rustc_middle`.
pub trait HashStableContext: pub trait HashStableContext: rustc_span::HashStableContext {
rustc_type_ir::HashStableContext + rustc_span::HashStableContext
{
fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher); fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher);
} }

View File

@ -38,51 +38,80 @@ fn parse_attributes(field: &syn::Field) -> Attributes {
attrs attrs
} }
pub(crate) fn hash_stable_generic_derive( pub(crate) fn hash_stable_derive(s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
mut s: synstructure::Structure<'_>, hash_stable_derive_with_mode(s, HashStableMode::Normal)
) -> 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 });
let discriminant = hash_stable_discriminant(&mut s);
let body = hash_stable_body(&mut s);
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 { pub(crate) fn hash_stable_generic_derive(
let generic: syn::GenericParam = parse_quote!('__ctx); s: synstructure::Structure<'_>,
s.add_bounds(synstructure::AddBounds::Generics); ) -> proc_macro2::TokenStream {
hash_stable_derive_with_mode(s, HashStableMode::Generic)
}
pub(crate) fn hash_stable_no_context_derive(
s: synstructure::Structure<'_>,
) -> proc_macro2::TokenStream {
hash_stable_derive_with_mode(s, HashStableMode::NoContext)
}
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,
}
fn hash_stable_derive_with_mode(
mut s: synstructure::Structure<'_>,
mode: HashStableMode,
) -> proc_macro2::TokenStream {
let generic: syn::GenericParam = match mode {
HashStableMode::Normal => parse_quote!('__ctx),
HashStableMode::Generic | HashStableMode::NoContext => parse_quote!(__CTX),
};
// 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 => {}
}
s.add_impl_generic(generic); s.add_impl_generic(generic);
let discriminant = hash_stable_discriminant(&mut s); let discriminant = hash_stable_discriminant(&mut s);
let body = hash_stable_body(&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( s.bound_impl(
quote!( quote!(
::rustc_data_structures::stable_hasher::HashStable< ::rustc_data_structures::stable_hasher::HashStable<
::rustc_query_system::ich::StableHashingContext<'__ctx>, #context
> >
), ),
quote! { quote! {
#[inline] #[inline]
fn hash_stable( fn hash_stable(
&self, &self,
__hcx: &mut ::rustc_query_system::ich::StableHashingContext<'__ctx>, __hcx: &mut #context,
__hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
#discriminant #discriminant
match *self { #body } match *self { #body }

View File

@ -48,6 +48,13 @@ decl_derive!(
[HashStable_Generic, attributes(stable_hasher)] => [HashStable_Generic, attributes(stable_hasher)] =>
hash_stable::hash_stable_generic_derive 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!([Decodable] => serialize::decodable_derive);
decl_derive!([Encodable] => serialize::encodable_derive); decl_derive!([Encodable] => serialize::encodable_derive);

View File

@ -123,5 +123,3 @@ impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
}); });
} }
} }
impl<'ctx> rustc_type_ir::HashStableContext for StableHashingContext<'ctx> {}

View File

@ -2,9 +2,6 @@ use std::fmt;
use std::hash::Hash; use std::hash::Hash;
use std::ops::ControlFlow; use std::ops::ControlFlow;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::fold::{FallibleTypeFolder, TypeFoldable};
use crate::visit::{TypeVisitable, TypeVisitor}; use crate::visit::{TypeVisitable, TypeVisitor};
use crate::{Interner, UniverseIndex}; use crate::{Interner, UniverseIndex};
@ -14,7 +11,7 @@ use crate::{Interner, UniverseIndex};
/// numbered starting from 0 in order of first appearance. /// numbered starting from 0 in order of first appearance.
#[derive(derivative::Derivative)] #[derive(derivative::Derivative)]
#[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))] #[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<I: Interner, V> { pub struct Canonical<I: Interner, V> {
pub value: V, pub value: V,
pub max_universe: UniverseIndex, pub max_universe: UniverseIndex,
@ -61,19 +58,6 @@ impl<I: Interner, V> Canonical<I, V> {
} }
} }
#[cfg(feature = "nightly")]
impl<CTX: crate::HashStableContext, I: Interner, V: HashStable<CTX>> HashStable<CTX>
for Canonical<I, V>
where
I::CanonicalVars: HashStable<CTX>,
{
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<I: Interner, V: Eq> Eq for Canonical<I, V> {} impl<I: Interner, V: Eq> Eq for Canonical<I, V> {}
impl<I: Interner, V: PartialEq> PartialEq for Canonical<I, V> { impl<I: Interner, V: PartialEq> PartialEq for Canonical<I, V> {

View File

@ -16,7 +16,7 @@ use self::ConstKind::*;
Ord = "feature_allow_slow_enum", Ord = "feature_allow_slow_enum",
Hash(bound = "") Hash(bound = "")
)] )]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum ConstKind<I: Interner> { pub enum ConstKind<I: Interner> {
/// A const generic parameter. /// A const generic parameter.
Param(I::ParamConst), Param(I::ParamConst),
@ -47,49 +47,6 @@ pub enum ConstKind<I: Interner> {
Expr(I::ExprConst), Expr(I::ExprConst),
} }
#[cfg(feature = "nightly")]
const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize {
match value {
Param(_) => 0,
Infer(_) => 1,
Bound(_, _) => 2,
Placeholder(_) => 3,
Unevaluated(_) => 4,
Value(_) => 5,
Error(_) => 6,
Expr(_) => 7,
}
}
#[cfg(feature = "nightly")]
impl<CTX: crate::HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I>
where
I::ParamConst: HashStable<CTX>,
I::BoundConst: HashStable<CTX>,
I::PlaceholderConst: HashStable<CTX>,
I::AliasConst: HashStable<CTX>,
I::ValueConst: HashStable<CTX>,
I::ErrorGuaranteed: HashStable<CTX>,
I::ExprConst: HashStable<CTX>,
{
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<I: Interner> PartialEq for ConstKind<I> { impl<I: Interner> PartialEq for ConstKind<I> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
match (self, other) { match (self, other) {

View File

@ -51,9 +51,6 @@ pub use region_kind::*;
pub use ty_info::*; pub use ty_info::*;
pub use ty_kind::*; pub use ty_kind::*;
/// Needed so we can use #[derive(HashStable_Generic)]
pub trait HashStableContext {}
rustc_index::newtype_index! { rustc_index::newtype_index! {
/// A [De Bruijn index][dbi] is a standard means of representing /// A [De Bruijn index][dbi] is a standard means of representing
/// regions (and perhaps later types) in a higher-ranked setting. In /// regions (and perhaps later types) in a higher-ranked setting. In
@ -94,7 +91,7 @@ rustc_index::newtype_index! {
/// is the outer fn. /// is the outer fn.
/// ///
/// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index /// [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({})"] #[debug_format = "DebruijnIndex({})"]
#[gate_rustc_only] #[gate_rustc_only]
pub struct DebruijnIndex { pub struct DebruijnIndex {
@ -179,7 +176,7 @@ pub fn debug_bound_var<T: std::fmt::Write>(
} }
#[derive(Copy, Clone, PartialEq, Eq)] #[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)] #[cfg_attr(feature = "nightly", rustc_pass_by_value)]
pub enum Variance { pub enum Variance {
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type Covariant, // T<A> <: T<B> 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 /// declared, but a type name in a non-zero universe is a placeholder
/// type -- an idealized representative of "types in general" that we /// type -- an idealized representative of "types in general" that we
/// use for checking generic functions. /// use for checking generic functions.
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
#[debug_format = "U{}"] #[debug_format = "U{}"]
#[gate_rustc_only] #[gate_rustc_only]
pub struct UniverseIndex {} pub struct UniverseIndex {}

View File

@ -1,5 +1,3 @@
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use std::fmt; use std::fmt;
use std::ops::ControlFlow; use std::ops::ControlFlow;
@ -11,7 +9,7 @@ use crate::Interner;
/// by implied bounds. /// by implied bounds.
#[derive(derivative::Derivative)] #[derive(derivative::Derivative)]
#[derivative(Clone(bound = ""), Hash(bound = ""))] #[derivative(Clone(bound = ""), Hash(bound = ""))]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum ClauseKind<I: Interner> { pub enum ClauseKind<I: Interner> {
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
/// the `Self` type of the trait reference and `A`, `B`, and `C` /// the `Self` type of the trait reference and `A`, `B`, and `C`
@ -68,47 +66,6 @@ impl<I: Interner> PartialEq for ClauseKind<I> {
impl<I: Interner> Eq for ClauseKind<I> {} impl<I: Interner> Eq for ClauseKind<I> {}
#[cfg(feature = "nightly")]
fn clause_kind_discriminant<I: Interner>(value: &ClauseKind<I>) -> 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<CTX: crate::HashStableContext, I: Interner> HashStable<CTX> for ClauseKind<I>
where
I::Ty: HashStable<CTX>,
I::Const: HashStable<CTX>,
I::GenericArg: HashStable<CTX>,
I::TraitPredicate: HashStable<CTX>,
I::ProjectionPredicate: HashStable<CTX>,
I::TypeOutlivesPredicate: HashStable<CTX>,
I::RegionOutlivesPredicate: HashStable<CTX>,
{
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<I: Interner> TypeFoldable<I> for ClauseKind<I> impl<I: Interner> TypeFoldable<I> for ClauseKind<I>
where where
I::Ty: TypeFoldable<I>, I::Ty: TypeFoldable<I>,
@ -164,7 +121,7 @@ where
#[derive(derivative::Derivative)] #[derive(derivative::Derivative)]
#[derivative(Clone(bound = ""), Hash(bound = ""))] #[derivative(Clone(bound = ""), Hash(bound = ""))]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum PredicateKind<I: Interner> { pub enum PredicateKind<I: Interner> {
/// Prove a clause /// Prove a clause
Clause(ClauseKind<I>), Clause(ClauseKind<I>),
@ -242,58 +199,6 @@ impl<I: Interner> PartialEq for PredicateKind<I> {
impl<I: Interner> Eq for PredicateKind<I> {} impl<I: Interner> Eq for PredicateKind<I> {}
#[cfg(feature = "nightly")]
fn predicate_kind_discriminant<I: Interner>(value: &PredicateKind<I>) -> 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<CTX: crate::HashStableContext, I: Interner> HashStable<CTX> for PredicateKind<I>
where
I::DefId: HashStable<CTX>,
I::Const: HashStable<CTX>,
I::GenericArgs: HashStable<CTX>,
I::Term: HashStable<CTX>,
I::CoercePredicate: HashStable<CTX>,
I::SubtypePredicate: HashStable<CTX>,
I::ClosureKind: HashStable<CTX>,
ClauseKind<I>: HashStable<CTX>,
{
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<I: Interner> TypeFoldable<I> for PredicateKind<I> impl<I: Interner> TypeFoldable<I> for PredicateKind<I>
where where
I::DefId: TypeFoldable<I>, I::DefId: TypeFoldable<I>,
@ -366,7 +271,7 @@ where
} }
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] #[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 { pub enum AliasRelationDirection {
Equate, Equate,
Subtype, Subtype,

View File

@ -263,7 +263,7 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
// This is not a derived impl because a derive would require `I: HashStable` // This is not a derived impl because a derive would require `I: HashStable`
impl<CTX: crate::HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I> impl<CTX, I: Interner> HashStable<CTX> for RegionKind<I>
where where
I::EarlyParamRegion: HashStable<CTX>, I::EarlyParamRegion: HashStable<CTX>,
I::BoundRegion: HashStable<CTX>, I::BoundRegion: HashStable<CTX>,

View File

@ -14,7 +14,7 @@ use self::TyKind::*;
/// The movability of a coroutine / closure literal: /// The movability of a coroutine / closure literal:
/// whether a coroutine contains self-references, causing it to be `!Unpin`. /// whether a coroutine contains self-references, causing it to be `!Unpin`.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] #[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 { pub enum Movability {
/// May contain self-references, `!Unpin`. /// May contain self-references, `!Unpin`.
Static, Static,
@ -23,7 +23,7 @@ pub enum Movability {
} }
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] #[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 { pub enum Mutability {
// N.B. Order is deliberate, so that Not < Mut // N.B. Order is deliberate, so that Not < Mut
Not, Not,
@ -75,7 +75,7 @@ impl Mutability {
/// Specifies how a trait object is represented. /// Specifies how a trait object is represented.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[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 { pub enum DynKind {
/// An unsized `dyn Trait` object /// An unsized `dyn Trait` object
Dyn, Dyn,
@ -89,7 +89,7 @@ pub enum DynKind {
} }
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[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 { pub enum AliasKind {
/// A projection `<Type as Trait>::AssocType`. /// A projection `<Type as Trait>::AssocType`.
/// Can get normalized away if monomorphic enough. /// Can get normalized away if monomorphic enough.
@ -119,7 +119,7 @@ pub enum AliasKind {
Ord = "feature_allow_slow_enum", Ord = "feature_allow_slow_enum",
Hash(bound = "") Hash(bound = "")
)] )]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum TyKind<I: Interner> { pub enum TyKind<I: Interner> {
/// The primitive boolean type. Written as `bool`. /// The primitive boolean type. Written as `bool`.
Bool, Bool,
@ -472,120 +472,8 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
} }
} }
// This is not a derived impl because a derive would require `I: HashStable`
#[cfg(feature = "nightly")]
#[allow(rustc::usage_of_ty_tykind)]
impl<CTX: crate::HashStableContext, I: Interner> HashStable<CTX> for TyKind<I>
where
I::AdtDef: HashStable<CTX>,
I::DefId: HashStable<CTX>,
I::GenericArgs: HashStable<CTX>,
I::Ty: HashStable<CTX>,
I::Const: HashStable<CTX>,
I::TypeAndMut: HashStable<CTX>,
I::PolyFnSig: HashStable<CTX>,
I::BoundExistentialPredicates: HashStable<CTX>,
I::Region: HashStable<CTX>,
I::Tys: HashStable<CTX>,
I::AliasTy: HashStable<CTX>,
I::BoundTy: HashStable<CTX>,
I::ParamTy: HashStable<CTX>,
I::PlaceholderTy: HashStable<CTX>,
I::ErrorGuaranteed: HashStable<CTX>,
{
#[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(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 { pub enum IntTy {
Isize, Isize,
I8, I8,
@ -643,7 +531,7 @@ impl IntTy {
} }
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] #[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 { pub enum UintTy {
Usize, Usize,
U8, U8,
@ -701,7 +589,7 @@ impl UintTy {
} }
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[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 { pub enum FloatTy {
F32, F32,
F64, F64,