Skip to content

Commit

Permalink
feat(exporter): introduce PredicateId
Browse files Browse the repository at this point in the history
  • Loading branch information
W95Psp committed May 15, 2024
1 parent 153c496 commit a9e63c3
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 0 deletions.
2 changes: 2 additions & 0 deletions frontend/exporter/src/types/new/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
//! Rustc.
mod item_attributes;
mod predicate_id;
mod typed_constant_kind;

pub use item_attributes::*;
pub use predicate_id::*;
pub use typed_constant_kind::*;
65 changes: 65 additions & 0 deletions frontend/exporter/src/types/new/predicate_id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use crate::prelude::*;
use rustc_middle::ty;

#[derive(
Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord,
)]
#[serde(transparent)]
/// A `PredicateId` is a unique identifier for a clause or a
/// predicate. It is computed by hashing predicates and clause in a
/// uniform and deterministic way.
pub struct PredicateId(u64);

/// Implemented by anything that can be assimilated to a predicate.
pub trait IntoPredicateId<'tcx, S: UnderOwnerState<'tcx>> {
/// Compute a consistent `PredicateId`
fn predicate_id(&self, s: &S) -> PredicateId;
}

impl<'tcx, S: UnderOwnerState<'tcx>> IntoPredicateId<'tcx, S> for ty::Clause<'tcx> {
fn predicate_id(&self, s: &S) -> PredicateId {
self.as_predicate().predicate_id(s)
}
}

impl<'tcx, S: UnderOwnerState<'tcx>> IntoPredicateId<'tcx, S> for ty::Predicate<'tcx> {
fn predicate_id(&self, s: &S) -> PredicateId {
// Here, we need to be careful about not hashing a `crate::Predicate`,
// but `crate::Binder<crate::PredicateKind>` instead,
// otherwise we would get into a infinite recursion.
let poly_kind: Binder<PredicateKind> = self.kind().sinto(s);
PredicateId(deterministic_hash(&poly_kind))
}
}

impl<'tcx, S: UnderOwnerState<'tcx>> IntoPredicateId<'tcx, S> for ty::PolyTraitPredicate<'tcx> {
fn predicate_id(&self, s: &S) -> PredicateId {
use ty::ToPredicate;
let predicate: ty::Predicate<'tcx> = (*self).to_predicate(s.base().tcx);
predicate.predicate_id(s)
}
}

/// A `PredicateId` can be mapped to itself via SInto. This is useful
/// for mirroring the type [`traits::search_clause::PathChunk`] as
/// [`traits::ImplExprPathChunk`].
impl<'tcx, S: UnderOwnerState<'tcx>> SInto<S, PredicateId> for PredicateId {
fn sinto(&self, _s: &S) -> PredicateId {
*self
}
}

/// We need identifiers that are stable across different
/// architectures, different paths (which are observable from
/// `Span`s), etc.
/// Rustc's stable hash is not doing what we want here: it is sensible
/// to the environment. Instead, we first `sinto` and then hash with
/// `deterministic_hash` below.
fn deterministic_hash<T: std::hash::Hash>(x: &T) -> u64 {
use crate::deterministic_hash::DeterministicHasher;
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
let mut hasher = DeterministicHasher::new(DefaultHasher::new());
x.hash(&mut hasher);
hasher.finish()
}

0 comments on commit a9e63c3

Please sign in to comment.