From b260c7b60878ac38c7ae1dac4d936abe71b560e6 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 13 May 2024 19:22:44 +0200 Subject: [PATCH] wip --- frontend/exporter/src/traits.rs | 67 ++++++--------------------- frontend/exporter/src/types/copied.rs | 51 +++++++++----------- frontend/exporter/src/types/new.rs | 60 ++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 83 deletions(-) diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index 8492ce736..80900ae5b 100644 --- a/frontend/exporter/src/traits.rs +++ b/frontend/exporter/src/traits.rs @@ -9,12 +9,12 @@ pub enum ImplExprPathChunk { AssocItem { item: AssocItem, predicate: Binder, - clause_id: u64, + clause_id: PredicateId, index: usize, }, Parent { predicate: Binder, - clause_id: u64, + clause_id: PredicateId, index: usize, }, } @@ -32,7 +32,7 @@ pub enum ImplExprAtom { }, /// A context-bound clause like `where T: Trait`. LocalBound { - clause_id: u64, + clause_id: PredicateId, r#trait: Binder, path: Vec, }, @@ -73,6 +73,7 @@ pub struct ImplExpr { mod search_clause { use crate::prelude::UnderOwnerState; use crate::rustc_utils::*; + use crate::{IntoPredicateId, PredicateId}; use rustc_middle::ty::*; fn predicates_to_poly_trait_predicates<'tcx>( @@ -90,12 +91,12 @@ mod search_clause { AssocItem { item: AssocItem, predicate: PolyTraitPredicate<'tcx>, - clause_id: u64, + clause_id: PredicateId, index: usize, }, Parent { predicate: PolyTraitPredicate<'tcx>, - clause_id: u64, + clause_id: PredicateId, index: usize, }, } @@ -224,10 +225,7 @@ mod search_clause { cons( PathChunk::Parent { predicate: p, - clause_id: { - use rustc_middle::ty::ToPredicate; - crate::clause_id_of_predicate(s, p.to_predicate(s.base().tcx)) - }, + clause_id: p.clause_id(s), index, }, path, @@ -244,13 +242,7 @@ mod search_clause { cons( PathChunk::AssocItem { item, - clause_id: { - use rustc_middle::ty::ToPredicate; - crate::clause_id_of_predicate( - s, - p.to_predicate(s.base().tcx), - ) - }, + clause_id: p.clause_id(s), predicate: p, index, }, @@ -374,7 +366,7 @@ impl<'tcx> IntoImplExpr<'tcx> for rustc_middle::ty::PolyTraitRef<'tcx> { .with_args(impl_exprs(s, &nested), trait_ref) } else { ImplExprAtom::LocalBound { - clause_id: clause_id_of_predicate(s, apred.predicate), + clause_id: apred.predicate.clause_id(s), r#trait, path, } @@ -415,8 +407,9 @@ pub fn super_clause_to_clause_and_impl_expr<'tcx, S: UnderOwnerState<'tcx>>( // original clause id (with, i.e., `Self`) let s = &with_owner_id(s.base(), (), (), impl_trait_ref.def_id()); // We compute the id of the clause without binder. - let clause: Clause = clause.kind().skip_binder().sinto(s); - clause.id + // let clause: Clause = clause.sinto(s); + // clause.id + clause.clause_id(s) }; let new_clause = clause.subst_supertrait(tcx, &impl_trait_ref); let impl_expr = new_clause @@ -424,45 +417,11 @@ pub fn super_clause_to_clause_and_impl_expr<'tcx, S: UnderOwnerState<'tcx>>( .to_opt_poly_trait_pred()? .impl_expr(s, get_param_env(s)); // Build the new clause, again without binder. - let mut new_clause_no_binder: Clause = new_clause.kind().skip_binder().sinto(s); + let mut new_clause_no_binder = new_clause.sinto(s); new_clause_no_binder.id = original_clause_id; Some((new_clause_no_binder, impl_expr, span.sinto(s))) } -fn deterministic_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() -} - -/// Crafts a unique identifier for a predicate by hashing it. The hash -/// is non-trivial because we need stable identifiers: two hax -/// extraction of a same predicate should result in the same -/// identifier. Rustc's stable hash is not doing what we want here: it -/// is sensible to the environment. Instead, we convert the (rustc) -/// predicate to `crate::Predicate` and hash from there. -#[tracing::instrument(level = "trace", skip(s))] -pub fn clause_id_of_predicate<'tcx, S: UnderOwnerState<'tcx>>( - s: &S, - predicate: rustc_middle::ty::Predicate<'tcx>, -) -> u64 { - let predicate = predicate.sinto(s); - match &predicate.value { - // Instead of recursively hashing the clause, we reuse the already-computed id. - PredicateKind::Clause(clause) => clause.id, - _ => deterministic_hash(&(1u8, predicate)), - } -} - -/// Used when building a `crate::Clause`. See [`clause_id_of_predicate`] for what we're doing here. -#[tracing::instrument(level = "trace")] -pub fn clause_id_of_bound_clause_kind(binder: &Binder) -> u64 { - deterministic_hash(&(0u8, binder)) -} - #[tracing::instrument(level = "trace", skip(s))] pub fn select_trait_candidate<'tcx, S: UnderOwnerState<'tcx>>( s: &S, diff --git a/frontend/exporter/src/types/copied.rs b/frontend/exporter/src/types/copied.rs index 51008319b..fc5db1901 100644 --- a/frontend/exporter/src/types/copied.rs +++ b/frontend/exporter/src/types/copied.rs @@ -3275,35 +3275,37 @@ pub enum ClauseKind { TypeWellFormedFromEnv(Ty), } -/// Reflects [`rustc_middle::ty::ClauseKind`] and adds a hash-consed clause identifier. +/// Reflects [`rustc_middle::ty::Clause`] and adds a hash-consed clause identifier. #[derive( Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, )] pub struct Clause { - pub kind: ClauseKind, - pub id: u64, + pub kind: Binder, + pub id: PredicateId, } -impl<'tcx, S: UnderOwnerState<'tcx>> SInto - for rustc_middle::ty::Binder<'tcx, rustc_middle::ty::ClauseKind<'tcx>> -{ +impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::Clause<'tcx> { fn sinto(&self, s: &S) -> Clause { - // FIXME: `ClauseKind::sinto` uses a dummy binder. We need it because `Predicate::sinto()` - // doesn't propagate the binder to the `ClauseKind`. This might cause inconsistencies. It - // might be that we don't want to hash the binder at all. - let binder: Binder = self.sinto(s); - let id = clause_id_of_bound_clause_kind(&binder); - Clause { - kind: binder.value, - id, - } + let kind: Binder = self.kind().sinto(s); + let id = self.clause_id(s); + Clause { kind, id } } } -impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::ClauseKind<'tcx> { - fn sinto(&self, s: &S) -> Clause { - // FIXME: this is dangerous. - rustc_middle::ty::Binder::dummy(self.clone()).sinto(s) +/// Reflects [`rustc_middle::ty::Predicate`] and adds a hash-consed clause identifier. +#[derive( + Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, +)] +pub struct Predicate { + pub kind: Binder, + pub id: PredicateId, +} + +impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::Predicate<'tcx> { + fn sinto(&self, s: &S) -> Predicate { + let kind: Binder = self.kind().sinto(s); + let id = self.clause_id(s); + Predicate { kind, id } } } @@ -3341,9 +3343,6 @@ pub struct GenericPredicates { pub predicates: Vec<(Predicate, Span)>, } -/// Reflects [`rustc_middle::ty::Predicate`] -pub type Predicate = Binder; - impl<'tcx, S: UnderOwnerState<'tcx>, T1, T2> SInto> for rustc_middle::ty::Binder<'tcx, T1> where @@ -3356,12 +3355,6 @@ where } } -impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::Predicate<'tcx> { - fn sinto(&self, s: &S) -> Predicate { - self.kind().sinto(s) - } -} - /// Reflects [`rustc_middle::ty::SubtypePredicate`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::SubtypePredicate<'tcx>, state: S as tcx)] @@ -3415,7 +3408,7 @@ pub enum ClosureKind { Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, )] pub enum PredicateKind { - Clause(Clause), + Clause(ClauseKind), ObjectSafe(DefId), ClosureKind(DefId, Vec, ClosureKind), Subtype(SubtypePredicate), diff --git a/frontend/exporter/src/types/new.rs b/frontend/exporter/src/types/new.rs index e67658032..4ad56d4e1 100644 --- a/frontend/exporter/src/types/new.rs +++ b/frontend/exporter/src/types/new.rs @@ -70,3 +70,63 @@ impl ItemAttributes { } } } + +#[derive( + Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, +)] +#[serde(transparent)] +/// A `PredicateId` is a unique identifier for a clause or predicate +/// constructing by hashing it. +pub struct PredicateId(u64); + +/// `IntoPredicateId` provides a method `clause_id` that dervies a clause +/// identifier by hashing `self`. +pub trait IntoPredicateId<'tcx, S: UnderOwnerState<'tcx>> { + fn clause_id(&self, s: &S) -> PredicateId; +} + +const _: () = { + use rustc_middle::ty; + + /// The hash is non-trivial because we need stable identifiers: + /// two hax extraction of a same predicate should result in the + /// same identifier. Rustc's stable hash is not doing what we want + /// here: it is sensible to the environment. Instead, we convert + /// the (rustc) Predicate or ClauseKind to the hax versions of + /// Predicate or ClauseKind and compute a deterministic hash from + /// there. + fn deterministic_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() + } + + impl<'tcx, S: UnderOwnerState<'tcx>> IntoPredicateId<'tcx, S> for ty::Clause<'tcx> { + fn clause_id(&self, s: &S) -> PredicateId { + self.as_predicate().clause_id(s) + } + } + + impl<'tcx, S: UnderOwnerState<'tcx>> IntoPredicateId<'tcx, S> for ty::Predicate<'tcx> { + fn clause_id(&self, s: &S) -> PredicateId { + PredicateId(deterministic_hash(&self.sinto(s))) + } + } + + impl<'tcx, S: UnderOwnerState<'tcx>> IntoPredicateId<'tcx, S> for ty::PolyTraitPredicate<'tcx> { + fn clause_id(&self, s: &S) -> PredicateId { + use crate::rustc_middle::ty::ToPredicate; + let predicate: ty::Predicate<'tcx> = (*self).to_predicate(s.base().tcx); + predicate.clause_id(s) + } + } + + impl<'tcx, S: UnderOwnerState<'tcx>> SInto for PredicateId { + fn sinto(&self, _s: &S) -> PredicateId { + *self + } + } +};