Skip to content

Commit

Permalink
Add HashStable_NoContext to simplify HashStable implementations in ru…
Browse files Browse the repository at this point in the history
…stc_type_ir
  • Loading branch information
compiler-errors committed Nov 17, 2023
1 parent 069a4af commit 543d9d3
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 292 deletions.
4 changes: 1 addition & 3 deletions compiler/rustc_ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
44 changes: 44 additions & 0 deletions compiler/rustc_macros/src/hash_stable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_query_system/src/ich/impls_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,3 @@ impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
});
}
}

impl<'ctx> rustc_type_ir::HashStableContext for StableHashingContext<'ctx> {}
17 changes: 2 additions & 15 deletions compiler/rustc_type_ir/src/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<I: Interner, V> {
pub value: V,
pub max_universe: UniverseIndex,
Expand Down Expand Up @@ -60,17 +58,6 @@ impl<I: Interner, V> Canonical<I, V> {
}
}

impl<CTX: 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: PartialEq> PartialEq for Canonical<I, V> {
Expand Down
48 changes: 2 additions & 46 deletions compiler/rustc_type_ir/src/const_kind.rs
Original file line number Diff line number Diff line change
@@ -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::*;

Expand All @@ -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<I: Interner> {
/// A const generic parameter.
Param(I::ParamConst),
Expand Down Expand Up @@ -47,48 +45,6 @@ pub enum ConstKind<I: Interner> {
Expr(I::ExprConst),
}

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,
}
}

impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I>
where
I::ParamConst: HashStable<CTX>,
I::InferConst: 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> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
Expand Down
9 changes: 3 additions & 6 deletions compiler/rustc_type_ir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -173,7 +170,7 @@ pub fn debug_bound_var<T: std::fmt::Write>(
}
}

#[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<A> <: T<B> iff A <: B -- e.g., function return type
Expand Down Expand Up @@ -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 {}
}
Expand Down
98 changes: 4 additions & 94 deletions compiler/rustc_type_ir/src/predicate_kind.rs
Original file line number Diff line number Diff line change
@@ -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<I: Interner> {
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
/// the `Self` type of the trait reference and `A`, `B`, and `C`
Expand Down Expand Up @@ -67,45 +66,6 @@ impl<I: Interner> PartialEq for ClauseKind<I> {

impl<I: Interner> Eq for ClauseKind<I> {}

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,
}
}

impl<CTX: 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>
where
I::Ty: TypeFoldable<I>,
Expand Down Expand Up @@ -161,7 +121,7 @@ where

#[derive(derivative::Derivative)]
#[derivative(Clone(bound = ""), Hash(bound = ""))]
#[derive(TyEncodable, TyDecodable)]
#[derive(TyEncodable, TyDecodable, HashStable_NoContext)]
pub enum PredicateKind<I: Interner> {
/// Prove a clause
Clause(ClauseKind<I>),
Expand Down Expand Up @@ -239,56 +199,6 @@ impl<I: Interner> PartialEq for PredicateKind<I> {

impl<I: Interner> Eq for PredicateKind<I> {}

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,
}
}

impl<CTX: 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>
where
I::DefId: TypeFoldable<I>,
Expand Down Expand Up @@ -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,
Expand Down
7 changes: 3 additions & 4 deletions compiler/rustc_type_ir/src/region_kind.rs
Original file line number Diff line number Diff line change
@@ -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::*;

Expand Down Expand Up @@ -262,7 +261,7 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
}

// This is not a derived impl because a derive would require `I: HashStable`
impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I>
impl<CTX, I: Interner> HashStable<CTX> for RegionKind<I>
where
I::EarlyParamRegion: HashStable<CTX>,
I::BoundRegion: HashStable<CTX>,
Expand Down
Loading

0 comments on commit 543d9d3

Please sign in to comment.