diff --git a/engine/lib/concrete_ident/impl_infos.ml b/engine/lib/concrete_ident/impl_infos.ml index da1257d4e..57a6a915c 100644 --- a/engine/lib/concrete_ident/impl_infos.ml +++ b/engine/lib/concrete_ident/impl_infos.ml @@ -6,8 +6,8 @@ type t = { [impl] block is an {{: https://doc.rust-lang.org/reference/items/implementations.html#inherent-implementations } inherent [impl]}. *) typ : Ast.Rust.ty; (** The type implemented by the [impl] block. *) - predicates : Ast.Rust.trait_goal list; - (** The predicates that constraint this [impl] block. *) + clauses : Ast.Rust.trait_goal list; + (** The clauses that constraint this [impl] block. *) } (** metadata of an [impl] block *) @@ -20,17 +20,18 @@ issue 363}, when looking up certain identifiers generated by the engine, this function may return [None] even though the supplied identifier points to an [Impl] block. *) let lookup span (impl : Concrete_ident.t) : t option = - let* Types.{ generics = _; predicates; typ; trait_ref } = + let* Types.{ generics = _; clauses; typ; trait_ref } = Concrete_ident.lookup_raw_impl_info impl in let trait_goal = Option.map ~f:(Import_thir.import_trait_ref span) trait_ref in let typ = Import_thir.import_ty span typ in - let predicates = - let f (binder : Types.binder_for__predicate_kind) = - Import_thir.import_predicate_kind span binder.value + let clauses = + let f ((binder : Types.clause), span) = + Import_thir.import_clause span binder in - List.filter_map ~f predicates + List.filter_map ~f clauses + |> List.map ~f:(fun (i : Ast.Rust.impl_ident) -> i.goal) in - Some { trait_goal; typ; predicates } + Some { trait_goal; typ; clauses } diff --git a/engine/lib/import_thir.ml b/engine/lib/import_thir.ml index 77bb64069..8f92693bc 100644 --- a/engine/lib/import_thir.ml +++ b/engine/lib/import_thir.ml @@ -225,7 +225,6 @@ module type EXPR = sig val c_param : Thir.span -> Thir.param -> param val c_trait_item' : Thir.trait_item -> Thir.trait_item_kind -> trait_item' val c_trait_ref : Thir.span -> Thir.trait_ref -> trait_goal - val c_predicate_kind : Thir.span -> Thir.predicate_kind -> trait_goal option val c_impl_expr : Thir.span -> Thir.impl_expr -> impl_expr val c_clause : Thir.span -> Thir.clause -> impl_ident option end @@ -968,15 +967,21 @@ end) : EXPR = struct let browse_path (impl : impl_expr) (chunk : Thir.impl_expr_path_chunk) = match chunk with | AssocItem - { item; predicate = { value = { trait_ref; _ }; _ }; clause_id; _ } -> - let ident = { goal = c_trait_ref span trait_ref; name = clause_id } in + { item; predicate = { value = { trait_ref; _ }; _ }; predicate_id; _ } + -> + let ident = + { goal = c_trait_ref span trait_ref; name = predicate_id } + in let kind : Concrete_ident.Kind.t = match item.kind with Const | Fn -> Value | Type -> Type in let item = Concrete_ident.of_def_id kind item.def_id in Projection { impl; ident; item } - | Parent { predicate = { value = { trait_ref; _ }; _ }; clause_id; _ } -> - let ident = { goal = c_trait_ref span trait_ref; name = clause_id } in + | Parent { predicate = { value = { trait_ref; _ }; _ }; predicate_id; _ } + -> + let ident = + { goal = c_trait_ref span trait_ref; name = predicate_id } + in Parent { impl; ident } in match ie with @@ -984,8 +989,8 @@ end) : EXPR = struct let trait = Concrete_ident.of_def_id Impl id in let args = List.map ~f:(c_generic_value span) generics in Concrete { trait; args } - | LocalBound { clause_id; path; _ } -> - let init = LocalBound { id = clause_id } in + | LocalBound { predicate_id; path; _ } -> + let init = LocalBound { id = predicate_id } in List.fold ~init ~f:browse_path path | Dyn -> Dyn | SelfImpl { path; _ } -> List.fold ~init:Self ~f:browse_path path @@ -1042,8 +1047,7 @@ end) : EXPR = struct let attrs = c_attrs param.attributes in { ident; span; attrs; kind } - let c_clause span (p : Thir.clause) : impl_ident option = - let ({ kind; id } : Thir.clause) = p in + let c_clause_kind span id (kind : Thir.clause_kind) : impl_ident option = match kind with | Trait { is_positive = true; is_const = _; trait_ref } -> let args = List.map ~f:(c_generic_value span) trait_ref.generic_args in @@ -1051,11 +1055,9 @@ end) : EXPR = struct Some { goal = { trait; args }; name = id } | _ -> None - let c_predicate_kind' span (p : Thir.predicate_kind) : impl_ident option = - match p with Clause clause -> c_clause span clause | _ -> None - - let c_predicate_kind span (p : Thir.predicate_kind) : trait_goal option = - c_predicate_kind' span p |> Option.map ~f:(fun (x : impl_ident) -> x.goal) + let c_clause span (p : Thir.clause) : impl_ident option = + let ({ kind; id } : Thir.clause) = p in + c_clause_kind span id kind.value let list_dedup (equal : 'a -> 'a -> bool) : 'a list -> 'a list = let rec aux (seen : 'a list) (todo : 'a list) : 'a list = @@ -1069,7 +1071,7 @@ end) : EXPR = struct let c_generics (generics : Thir.generics) : generics = let bounds = - List.filter_map ~f:(c_predicate_kind' generics.span) generics.bounds + List.filter_map ~f:(c_clause generics.span) generics.bounds |> List.map ~f:(fun impl_ident -> GCType impl_ident) in { @@ -1098,7 +1100,7 @@ end) : EXPR = struct in TIFn (TArrow (inputs, output)) | Type (bounds, None) -> - let bounds = List.filter_map ~f:(c_predicate_kind' span) bounds in + let bounds = List.filter_map ~f:(c_clause span) bounds in TIType bounds | Type (_, Some _) -> unimplemented [ span ] @@ -1115,9 +1117,8 @@ include struct let import_trait_ref : Types.span -> Types.trait_ref -> Ast.Rust.trait_goal = c_trait_ref - let import_predicate_kind : - Types.span -> Types.predicate_kind -> Ast.Rust.trait_goal option = - c_predicate_kind + let import_clause : Types.span -> Types.clause -> Ast.Rust.impl_ident option = + c_clause end (** Instantiate the functor for translating expressions. The crate diff --git a/engine/lib/import_thir.mli b/engine/lib/import_thir.mli index 2ab0c3e5e..2d0374a63 100644 --- a/engine/lib/import_thir.mli +++ b/engine/lib/import_thir.mli @@ -1,8 +1,6 @@ val import_ty : Types.span -> Types.ty -> Ast.Rust.ty val import_trait_ref : Types.span -> Types.trait_ref -> Ast.Rust.trait_goal - -val import_predicate_kind : - Types.span -> Types.predicate_kind -> Ast.Rust.trait_goal option +val import_clause : Types.span -> Types.clause -> Ast.Rust.impl_ident option val import_item : drop_body:bool -> diff --git a/frontend/exporter/src/state.rs b/frontend/exporter/src/state.rs index 6cec3638e..26e1fc4f6 100644 --- a/frontend/exporter/src/state.rs +++ b/frontend/exporter/src/state.rs @@ -236,7 +236,7 @@ pub trait UnderOwnerState<'tcx> = BaseState<'tcx> + HasOwnerId; #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct ImplInfos { pub generics: TyGenerics, - pub predicates: Vec, + pub clauses: Vec<(Clause, Span)>, pub typ: Ty, pub trait_ref: Option, } @@ -246,17 +246,11 @@ impl ImplInfos { let tcx = base.tcx; let s = &with_owner_id(base, (), (), did); - let predicates = tcx - .predicates_defined_on(did) - .predicates - .iter() - .map(|(clause, _)| clause.as_predicate().sinto(s)) - .collect(); Self { generics: tcx.generics_of(did).sinto(s), typ: tcx.type_of(did).subst_identity().sinto(s), trait_ref: tcx.impl_trait_ref(did).sinto(s), - predicates, + clauses: tcx.predicates_defined_on(did).predicates.sinto(s), } } } diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index 8492ce736..fab6f50a4 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, + predicate_id: PredicateId, index: usize, }, Parent { predicate: Binder, - clause_id: u64, + predicate_id: PredicateId, index: usize, }, } @@ -32,7 +32,7 @@ pub enum ImplExprAtom { }, /// A context-bound clause like `where T: Trait`. LocalBound { - clause_id: u64, + predicate_id: PredicateId, r#trait: Binder, path: Vec, }, @@ -70,9 +70,11 @@ pub struct ImplExpr { pub args: Vec, } -mod search_clause { +// FIXME: this has visibility `pub(crate)` only because of https://github.com/rust-lang/rust/issues/83049 +pub(crate) 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 +92,12 @@ mod search_clause { AssocItem { item: AssocItem, predicate: PolyTraitPredicate<'tcx>, - clause_id: u64, + predicate_id: PredicateId, index: usize, }, Parent { predicate: PolyTraitPredicate<'tcx>, - clause_id: u64, + predicate_id: PredicateId, index: usize, }, } @@ -224,10 +226,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)) - }, + predicate_id: p.predicate_id(s), index, }, path, @@ -244,13 +243,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), - ) - }, + predicate_id: p.predicate_id(s), predicate: p, index, }, @@ -374,7 +367,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), + predicate_id: apred.predicate.predicate_id(s), r#trait, path, } @@ -410,59 +403,22 @@ pub fn super_clause_to_clause_and_impl_expr<'tcx, S: UnderOwnerState<'tcx>>( let impl_trait_ref = tcx .impl_trait_ref(impl_did) .map(|binder| rustc_middle::ty::Binder::dummy(binder.subst_identity()))?; - let original_clause_id = { + let original_predicate_id = { // We don't want the id of the substituted clause id, but the // 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 + clause.predicate_id(s) }; let new_clause = clause.subst_supertrait(tcx, &impl_trait_ref); let impl_expr = new_clause .as_predicate() .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); - new_clause_no_binder.id = original_clause_id; + let mut new_clause_no_binder = new_clause.sinto(s); + new_clause_no_binder.id = original_predicate_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..8a2b1ce26 100644 --- a/frontend/exporter/src/types/copied.rs +++ b/frontend/exporter/src/types/copied.rs @@ -3275,35 +3275,39 @@ 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 predicate 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, + kind: self.kind().sinto(s), + id: self.predicate_id(s), } } } -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 predicate 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 { + Predicate { + kind: self.kind().sinto(s), + id: self.predicate_id(s), + } } } @@ -3341,9 +3345,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 +3357,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 +3410,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), @@ -3426,7 +3421,7 @@ pub enum PredicateKind { } /// Reflects [`rustc_hir::GenericBounds`] -type GenericBounds = Vec; +type GenericBounds = Vec; /// Compute the bounds for the owner registed in the state `s` fn region_bounds_at_current_owner<'tcx, S: UnderOwnerState<'tcx>>(s: &S) -> GenericBounds { @@ -3467,13 +3462,7 @@ fn region_bounds_at_current_owner<'tcx, S: UnderOwnerState<'tcx>>(s: &S) -> Gene .copied() .collect() }; - clauses - .iter() - .map(|clause| { - tcx.erase_late_bound_regions(clause.as_predicate().kind()) - .sinto(s) - }) - .collect() + clauses.sinto(s) } impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_hir::GenericBounds<'tcx> {