From 6cee56ab9e24ff1e1ffa96d43bca306381414ecd Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 1 Jul 2025 13:10:07 +0200 Subject: [PATCH 01/51] Update rustc --- cli/driver/src/driver.rs | 1 - engine/lib/import_thir.ml | 18 +++++----- flake.lock | 6 ++-- .../exporter/src/constant_utils/uneval.rs | 4 +-- frontend/exporter/src/lib.rs | 2 +- frontend/exporter/src/sinto.rs | 6 ++++ frontend/exporter/src/traits/resolution.rs | 4 +-- frontend/exporter/src/types/hir.rs | 16 ++++----- frontend/exporter/src/types/new/full_def.rs | 5 +-- frontend/exporter/src/types/ty.rs | 6 ++-- rust-toolchain.toml | 2 +- ...oolchain__attribute-opaque into-fstar.snap | 2 ++ .../toolchain__attributes into-fstar.snap | 6 ++++ .../snapshots/toolchain__dyn into-fstar.snap | 34 +++++++++--------- .../toolchain__functions into-fstar.snap | 1 + .../toolchain__generics into-fstar.snap | 1 + .../toolchain__include-flag into-coq.snap | 4 +-- .../toolchain__include-flag into-fstar.snap | 4 ++- .../toolchain__interface-only into-fstar.snap | 2 ++ .../toolchain__literals into-coq.snap | 5 ++- .../toolchain__literals into-fstar.snap | 2 +- ..._mut-ref-functionalization into-fstar.snap | 1 + .../toolchain__naming into-fstar.snap | 36 ++++++++++++------- .../toolchain__side-effects into-fstar.snap | 1 + .../toolchain__traits into-fstar.snap | 36 ++++++++++++++++--- 25 files changed, 133 insertions(+), 72 deletions(-) diff --git a/cli/driver/src/driver.rs b/cli/driver/src/driver.rs index a7f1d4e2c..2ec019b8f 100644 --- a/cli/driver/src/driver.rs +++ b/cli/driver/src/driver.rs @@ -1,6 +1,5 @@ #![feature(rustc_private)] #![feature(box_patterns)] -#![feature(concat_idents)] #![feature(trait_alias)] #![allow(unused_imports)] #![allow(unused_variables)] diff --git a/engine/lib/import_thir.ml b/engine/lib/import_thir.ml index 830f4edc7..eecd488eb 100644 --- a/engine/lib/import_thir.ml +++ b/engine/lib/import_thir.ml @@ -1513,7 +1513,7 @@ and c_item_unwrapped ~ident ~type_only (item : Thir.item) : item list = in (* TODO: things might be unnamed (e.g. constants) *) match (item.kind : Thir.item_kind) with - | Const (_, _, generics, body) -> + | Const (_, generics, _, body) -> mk @@ Fn { @@ -1523,14 +1523,14 @@ and c_item_unwrapped ~ident ~type_only (item : Thir.item) : item list = params = []; safety = Safe; } - | Static (_, _, true, _) -> + | Static (true, _, _, _) -> unimplemented ~issue_id:1343 [ item.span ] "Mutable static items are not supported." - | Static (_, _ty, false, body) -> + | Static (false, _, _ty, body) -> let name = Concrete_ident.of_def_id ~value:true (assert_item_def_id ()) in let generics = { params = []; constraints = [] } in mk (Fn { name; generics; body = c_body body; params = []; safety = Safe }) - | TyAlias (_, ty, generics) -> + | TyAlias (_, generics, ty) -> mk @@ TyAlias { @@ -1549,13 +1549,13 @@ and c_item_unwrapped ~ident ~type_only (item : Thir.item) : item list = params = c_fn_params item.span params; safety = c_header_safety safety; } - | (Enum (_, _, generics, _) | Struct (_, _, generics)) when erased -> + | (Enum (_, generics, _, _) | Struct (_, generics, _)) when erased -> let generics = c_generics generics in let is_struct = match item.kind with Struct _ -> true | _ -> false in let def_id = assert_item_def_id () in let name = Concrete_ident.of_def_id ~value:false def_id in mk @@ Type { name; generics; variants = []; is_struct } - | Enum (_, variants, generics, repr) -> + | Enum (_, generics, variants, repr) -> let def_id = assert_item_def_id () in let generics = c_generics generics in let is_struct = false in @@ -1613,7 +1613,7 @@ and c_item_unwrapped ~ident ~type_only (item : Thir.item) : item list = mk_one (Type { name; generics; variants; is_struct }) :: discs in if is_primitive then cast_fun :: result else result - | Struct (_, v, generics) -> + | Struct (_, generics, v) -> let generics = c_generics generics in let def_id = assert_item_def_id () in let is_struct = true in @@ -1808,7 +1808,9 @@ and c_item_unwrapped ~ident ~type_only (item : Thir.item) : item list = { path = List.map ~f:(fun x -> fst x.ident) segments; is_external = - List.exists ~f:(function Err -> true | _ -> false) res; + List.exists + ~f:(function None | Some Err -> true | _ -> false) + res; (* TODO: this should represent local/external? *) rename; } diff --git a/flake.lock b/flake.lock index 08354fcfa..c263241e4 100644 --- a/flake.lock +++ b/flake.lock @@ -127,11 +127,11 @@ ] }, "locked": { - "lastModified": 1748399823, - "narHash": "sha256-kahD8D5hOXOsGbNdoLLnqCL887cjHkx98Izc37nDjlA=", + "lastModified": 1751338093, + "narHash": "sha256-/yd9nPcTfUZPFtwjRbdB5yGLdt3LTPqz6Ja63Joiahs=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "d68a69dc71bc19beb3479800392112c2f6218159", + "rev": "6cfb7821732dac2d3e2dea857a5613d3b856c20c", "type": "github" }, "original": { diff --git a/frontend/exporter/src/constant_utils/uneval.rs b/frontend/exporter/src/constant_utils/uneval.rs index 33d18f07d..8f41b2392 100644 --- a/frontend/exporter/src/constant_utils/uneval.rs +++ b/frontend/exporter/src/constant_utils/uneval.rs @@ -154,7 +154,7 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for ty::Const<'tcx> let span = self.default_span(s.base().tcx); match self.kind() { ty::ConstKind::Param(p) => { - let ty = p.find_ty_from_env(s.param_env()); + let ty = p.find_const_ty_from_env(s.param_env()); let kind = ConstantExprKind::ConstRef { id: p.sinto(s) }; kind.decorate(ty.sinto(s), span.sinto(s)) } @@ -279,7 +279,7 @@ fn op_to_const<'tcx, S: UnderOwnerState<'tcx>>( // Helper for struct-likes. let read_fields = |of: rustc_const_eval::interpret::OpTy<'tcx>, field_count| { (0..field_count).map(move |i| { - let field_op = ecx.project_field(&of, i)?; + let field_op = ecx.project_field(&of, rustc_abi::FieldIdx::from_usize(i))?; op_to_const(s, span, &ecx, field_op) }) }; diff --git a/frontend/exporter/src/lib.rs b/frontend/exporter/src/lib.rs index fe3b58896..a4c851910 100644 --- a/frontend/exporter/src/lib.rs +++ b/frontend/exporter/src/lib.rs @@ -1,9 +1,9 @@ #![allow(rustdoc::private_intra_doc_links)] -#![cfg_attr(feature = "rustc", feature(concat_idents))] #![cfg_attr(feature = "rustc", feature(if_let_guard))] #![cfg_attr(feature = "rustc", feature(let_chains))] #![cfg_attr(feature = "rustc", feature(macro_metavar_expr))] #![cfg_attr(feature = "rustc", feature(rustc_private))] +#![cfg_attr(feature = "rustc", feature(sized_hierarchy))] #![cfg_attr(feature = "rustc", feature(trait_alias))] #![cfg_attr(feature = "rustc", feature(type_changing_struct_update))] diff --git a/frontend/exporter/src/sinto.rs b/frontend/exporter/src/sinto.rs index fc58f735f..15d65f66b 100644 --- a/frontend/exporter/src/sinto.rs +++ b/frontend/exporter/src/sinto.rs @@ -1,9 +1,15 @@ use crate::prelude::{derive_group, JsonSchema}; +#[cfg(not(feature = "rustc"))] pub trait SInto { fn sinto(&self, s: &S) -> To; } +#[cfg(feature = "rustc")] +pub trait SInto: std::marker::PointeeSized { + fn sinto(&self, s: &S) -> To; +} + #[macro_export] macro_rules! sinto_todo { ($($mod:ident)::+, $type:ident$(<$($lts:lifetime),*$(,)?>)? as $renamed:ident) => { diff --git a/frontend/exporter/src/traits/resolution.rs b/frontend/exporter/src/traits/resolution.rs index 453a811ae..2b72db07d 100644 --- a/frontend/exporter/src/traits/resolution.rs +++ b/frontend/exporter/src/traits/resolution.rs @@ -677,7 +677,7 @@ pub fn shallow_resolve_trait_ref<'tcx>( use rustc_middle::traits::CodegenObligationError; use rustc_middle::ty::TypeVisitableExt; use rustc_trait_selection::traits::{ - Obligation, ObligationCause, ObligationCtxt, SelectionContext, Unimplemented, + Obligation, ObligationCause, ObligationCtxt, SelectionContext, SelectionError, }; // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. @@ -693,7 +693,7 @@ pub fn shallow_resolve_trait_ref<'tcx>( let selection = match selcx.poly_select(&obligation) { Ok(Some(selection)) => selection, Ok(None) => return Err(CodegenObligationError::Ambiguity), - Err(Unimplemented) => return Err(CodegenObligationError::Unimplemented), + Err(SelectionError::Unimplemented) => return Err(CodegenObligationError::Unimplemented), Err(_) => return Err(CodegenObligationError::Ambiguity), }; diff --git a/frontend/exporter/src/types/hir.rs b/frontend/exporter/src/types/hir.rs index e4b5a747b..2a80a7837 100644 --- a/frontend/exporter/src/types/hir.rs +++ b/frontend/exporter/src/types/hir.rs @@ -535,7 +535,7 @@ pub struct Variant { pub struct UsePath { pub span: Span, #[map(x.iter().map(|res| res.sinto(s)).collect())] - pub res: Vec, + pub res: Vec>, pub segments: Vec, #[value(self.segments.iter().last().and_then(|segment| { match s.base().tcx.hir_node_by_def_id(segment.hir_id.owner.def_id) { @@ -620,8 +620,8 @@ pub struct PathSegment { pub enum ItemKind { ExternCrate(Option, Ident), Use(UsePath, UseKind), - Static(Ident, Ty, Mutability, Body), - Const(Ident, Ty, Generics, Body), + Static(Mutability, Ident, Ty, Body), + Const(Ident, Generics, Ty, Body), #[custom_arm( hir::ItemKind::Fn{ ident, sig, generics, body, .. } => { ItemKind::Fn { @@ -648,6 +648,7 @@ pub enum ItemKind { }, TyAlias( Ident, + Generics, #[map({ let s = &State { base: Base {ty_alias_mode: true, ..s.base()}, @@ -659,20 +660,19 @@ pub enum ItemKind { x.sinto(s) })] Ty, - Generics, ), Enum( Ident, - EnumDef, Generics, + EnumDef, #[value({ let tcx = s.base().tcx; tcx.repr_options_of_def(s.owner_id().expect_local()).sinto(s) })] ReprOptions, ), - Struct(Ident, VariantData, Generics), - Union(Ident, VariantData, Generics), + Struct(Ident, Generics, VariantData), + Union(Ident, Generics, VariantData), Trait( IsAuto, Safety, @@ -916,7 +916,7 @@ impl<'tcx, S: BaseState<'tcx>, Body: IsBody> SInto> for hir::Item< let name = match self.kind { ExternCrate(_, i) | Use(_, hir::UseKind::Single(i)) - | Static(i, ..) + | Static(_, i, ..) | Const(i, ..) | Fn { ident: i, .. } | Macro(i, ..) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 951150d21..91a3e49a9 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -217,7 +217,7 @@ pub enum FullDefKind { /// `Some` if the item is in the local crate. #[value(s.base().tcx.hir_get_if_local(s.owner_id()).map(|node| { let rustc_hir::Node::Item(item) = node else { unreachable!() }; - let rustc_hir::ItemKind::TyAlias(_, ty, _generics) = &item.kind else { unreachable!() }; + let rustc_hir::ItemKind::TyAlias(_, _generics, ty) = &item.kind else { unreachable!() }; let mut s = State::from_under_owner(s); s.base.ty_alias_mode = true; ty.sinto(&s) @@ -981,7 +981,8 @@ fn closure_once_shim<'tcx>( #[cfg(feature = "rustc")] fn drop_glue_shim<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> Option> { - let drop_in_place = tcx.require_lang_item(rustc_hir::LangItem::DropInPlace, None); + let drop_in_place = + tcx.require_lang_item(rustc_hir::LangItem::DropInPlace, rustc_span::DUMMY_SP); if !tcx.generics_of(def_id).is_empty() { // Hack: layout code panics if it can't fully normalize types, which can happen e.g. with a // trait associated type. For now we only translate the glue for monomorphic types. diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index 0438ab5ee..49c9f2651 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -544,14 +544,14 @@ impl std::ops::Deref for ItemRef { #[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto for ty::GenericArg<'tcx> { fn sinto(&self, s: &S) -> GenericArg { - self.unpack().sinto(s) + self.kind().sinto(s) } } #[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto> for ty::GenericArgsRef<'tcx> { fn sinto(&self, s: &S) -> Vec { - self.iter().map(|v| v.unpack().sinto(s)).collect() + self.iter().map(|v| v.kind().sinto(s)).collect() } } @@ -1169,7 +1169,7 @@ pub enum Term { impl<'tcx, S: UnderOwnerState<'tcx>> SInto for ty::Term<'tcx> { fn sinto(&self, s: &S) -> Term { use ty::TermKind; - match self.unpack() { + match self.kind() { TermKind::Ty(ty) => Term::Ty(ty.sinto(s)), TermKind::Const(c) => Term::Const(c.sinto(s)), } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index f290a30ed..3a87a82e7 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-05-26" +channel = "nightly-2025-06-30" components = [ "rustc-dev", "llvm-tools-preview" , "rust-analysis" , "rust-src" , "rustfmt" ] diff --git a/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap b/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap index bc99d93be..21d95b115 100644 --- a/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap @@ -119,6 +119,7 @@ val ff_pre_post (x y: bool) result =. y) class t_T (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_U:Type0; f_c:u8; f_d_pre:Prims.unit -> Type0; @@ -133,6 +134,7 @@ class t_T (v_Self: Type0) = { val impl_T_for_u8:t_T u8 class t_TrGeneric (v_Self: Type0) (v_U: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; [@@@ FStar.Tactics.Typeclasses.no_method]_super_17240578109911634293:Core.Clone.t_Clone v_U; f_f_pre:v_U -> Type0; f_f_post:v_U -> v_Self -> Type0; diff --git a/test-harness/src/snapshots/toolchain__attributes into-fstar.snap b/test-harness/src/snapshots/toolchain__attributes into-fstar.snap index 4b29f6b9a..7dca84eb7 100644 --- a/test-harness/src/snapshots/toolchain__attributes into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__attributes into-fstar.snap @@ -155,6 +155,7 @@ open Core open FStar.Mul class t_T (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_v_pre:v_Self -> Type0; f_v_post:x: v_Self -> x_future: v_Self -> pred: Type0{pred ==> true}; f_v:x0: v_Self -> Prims.Pure v_Self (f_v_pre x0) (fun result -> f_v_post x0 result) @@ -214,6 +215,7 @@ let impl_SafeIndex__as_usize (self: t_SafeIndex) : usize = self.f_i let impl_1 (#v_T: Type0) : Core.Ops.Index.t_Index (t_Array v_T (mk_usize 10)) t_SafeIndex = { f_Output = v_T; + f_Output_6696274936538609082 = FStar.Tactics.Typeclasses.solve; f_index_pre = (fun (self: t_Array v_T (mk_usize 10)) (index: t_SafeIndex) -> true); f_index_post = (fun (self: t_Array v_T (mk_usize 10)) (index: t_SafeIndex) (out: v_T) -> true); f_index = fun (self: t_Array v_T (mk_usize 10)) (index: t_SafeIndex) -> self.[ index.f_i ] @@ -250,6 +252,7 @@ open Core open FStar.Mul class t_Operation (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_double_pre:x: u8 -> pred: Type0 @@ -306,6 +309,7 @@ let impl_Operation_for_ViaMul: t_Operation t_ViaMul = } class t_TraitWithRequiresAndEnsures (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_method_pre:self_: v_Self -> x: u8 -> pred: Type0{x <. mk_u8 100 ==> pred}; f_method_post:self_: v_Self -> x: u8 -> r: u8 -> pred: Type0{pred ==> r >. mk_u8 88}; f_method:x0: v_Self -> x1: u8 @@ -400,6 +404,7 @@ let mutation_example let impl: Core.Ops.Index.t_Index t_MyArray usize = { f_Output = u8; + f_Output_6696274936538609082 = FStar.Tactics.Typeclasses.solve; f_index_pre = (fun (self_: t_MyArray) (index: usize) -> index <. v_MAX); f_index_post = (fun (self: t_MyArray) (index: usize) (out: u8) -> true); f_index = fun (self: t_MyArray) (index: usize) -> self.[ index ] @@ -588,6 +593,7 @@ open Core open FStar.Mul class t_Foo (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_f_pre:x: u8 -> y: u8 -> pred: Type0 diff --git a/test-harness/src/snapshots/toolchain__dyn into-fstar.snap b/test-harness/src/snapshots/toolchain__dyn into-fstar.snap index 0928d26ad..75edb2282 100644 --- a/test-harness/src/snapshots/toolchain__dyn into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__dyn into-fstar.snap @@ -33,6 +33,7 @@ open Core open FStar.Mul class t_Printable (v_Self: Type0) (v_S: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_stringify_pre:v_Self -> Type0; f_stringify_post:v_Self -> v_S -> Type0; f_stringify:x0: v_Self @@ -54,27 +55,28 @@ let print Alloc.Boxed.t_Box (dyn 1 (fun z -> t_Printable z Alloc.String.t_String)) Alloc.Alloc.t_Global) : Prims.unit = + let args:t_Array Core.Fmt.Rt.t_Argument (mk_usize 1) = + let list = + [ + Core.Fmt.Rt.impl__new_display #Alloc.String.t_String + (f_stringify #(dyn 1 (fun z -> t_Printable z Alloc.String.t_String)) + #Alloc.String.t_String + #FStar.Tactics.Typeclasses.solve + a + <: + Alloc.String.t_String) + ] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 1); + Rust_primitives.Hax.array_of_list 1 list + in let _:Prims.unit = - Std.Io.Stdio.e_print (Core.Fmt.Rt.impl_2__new_v1 (mk_usize 2) + Std.Io.Stdio.e_print (Core.Fmt.Rt.impl_1__new_v1 (mk_usize 2) (mk_usize 1) (let list = [""; "\n"] in FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 2); Rust_primitives.Hax.array_of_list 2 list) - (let list = - [ - Core.Fmt.Rt.impl__new_display #Alloc.String.t_String - (f_stringify #(dyn 1 (fun z -> t_Printable z Alloc.String.t_String)) - #Alloc.String.t_String - #FStar.Tactics.Typeclasses.solve - a - <: - Alloc.String.t_String) - <: - Core.Fmt.Rt.t_Argument - ] - in - FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 1); - Rust_primitives.Hax.array_of_list 1 list) + args <: Core.Fmt.t_Arguments) in diff --git a/test-harness/src/snapshots/toolchain__functions into-fstar.snap b/test-harness/src/snapshots/toolchain__functions into-fstar.snap index df12b8b6e..f456755a4 100644 --- a/test-harness/src/snapshots/toolchain__functions into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__functions into-fstar.snap @@ -38,6 +38,7 @@ type t_CallableViaDeref = | CallableViaDeref : t_CallableViaDeref let impl: Core.Ops.Deref.t_Deref t_CallableViaDeref = { f_Target = Prims.unit -> bool; + f_Target_4695674276362814091 = FStar.Tactics.Typeclasses.solve; f_deref_pre = (fun (self: t_CallableViaDeref) -> true); f_deref_post = (fun (self: t_CallableViaDeref) (out: (Prims.unit -> bool)) -> true); f_deref diff --git a/test-harness/src/snapshots/toolchain__generics into-fstar.snap b/test-harness/src/snapshots/toolchain__generics into-fstar.snap index d42249d1c..c75680dca 100644 --- a/test-harness/src/snapshots/toolchain__generics into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__generics into-fstar.snap @@ -157,6 +157,7 @@ let call_g (_: Prims.unit) : usize = mk_usize 3 class t_Foo (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_const_add_pre:v_N: usize -> v_Self -> Type0; f_const_add_post:v_N: usize -> v_Self -> usize -> Type0; f_const_add:v_N: usize -> x0: v_Self diff --git a/test-harness/src/snapshots/toolchain__include-flag into-coq.snap b/test-harness/src/snapshots/toolchain__include-flag into-coq.snap index e0f975a26..b6d4c8c65 100644 --- a/test-harness/src/snapshots/toolchain__include-flag into-coq.snap +++ b/test-harness/src/snapshots/toolchain__include-flag into-coq.snap @@ -51,10 +51,10 @@ Record Foo_record : Type := #[export] Notation "'Foo_Foo_record'" := Build_Foo_record. -Class t_Trait (v_Self : Type) : Type := +Class t_Trait (v_Self : Type) `{t_MetaSized (v_Self)} : Type := { }. -Arguments t_Trait (_). +Arguments t_Trait (_) {_}. Instance t_Trait_572156424 : t_Trait ((t_Foo)) := { diff --git a/test-harness/src/snapshots/toolchain__include-flag into-fstar.snap b/test-harness/src/snapshots/toolchain__include-flag into-fstar.snap index 81212e6dd..45ac83394 100644 --- a/test-harness/src/snapshots/toolchain__include-flag into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__include-flag into-fstar.snap @@ -34,7 +34,9 @@ open FStar.Mul type t_Foo = | Foo : t_Foo -class t_Trait (v_Self: Type0) = { __marker_trait_t_Trait:Prims.unit } +class t_Trait (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self +} [@@ FStar.Tactics.Typeclasses.tcinstance] let impl: t_Trait t_Foo = { __marker_trait = () } diff --git a/test-harness/src/snapshots/toolchain__interface-only into-fstar.snap b/test-harness/src/snapshots/toolchain__interface-only into-fstar.snap index 7d30bbb68..b8c5290cc 100644 --- a/test-harness/src/snapshots/toolchain__interface-only into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__interface-only into-fstar.snap @@ -101,6 +101,7 @@ unfold let ff_generic (v_X: usize) (#v_U: Type0) = ff_generic' v_X #v_U class t_T (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_Assoc:Type0; f_d_pre:Prims.unit -> Type0; f_d_post:Prims.unit -> Prims.unit -> Type0; @@ -118,6 +119,7 @@ let impl_T_for_u8: t_T u8 = } class t_T2 (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_d_pre:Prims.unit -> Type0; f_d_post:Prims.unit -> Prims.unit -> Type0; f_d:x0: Prims.unit -> Prims.Pure Prims.unit (f_d_pre x0) (fun result -> f_d_post x0 result) diff --git a/test-harness/src/snapshots/toolchain__literals into-coq.snap b/test-harness/src/snapshots/toolchain__literals into-coq.snap index b6ff74d73..45268beae 100644 --- a/test-harness/src/snapshots/toolchain__literals into-coq.snap +++ b/test-harness/src/snapshots/toolchain__literals into-coq.snap @@ -45,8 +45,7 @@ From Core Require Import Core. (* NotImplementedYet *) -From Literals Require Import hax_lib. -Export hax_lib. + Definition math_integers (x : t_Int) `{andb (f_gt (x) (impl_Int__e_unsafe_from_str (("0"%string : string)))) (f_lt (x) (impl_Int__e_unsafe_from_str (("16"%string : string)))) = true} : t_u8 := let _ : t_Int := f_lift ((3 : t_usize)) in @@ -73,7 +72,7 @@ Definition math_integers (x : t_Int) `{andb (f_gt (x) (impl_Int__e_unsafe_from_s impl_Int__to_u8 (f_add (x) (f_mul (x) (x))). Definition panic_with_msg '(_ : unit) : unit := - never_to_any (panic_fmt (impl_2__new_const ([("with msg"%string : string)]))). + never_to_any (panic_fmt (impl_1__new_const ([("with msg"%string : string)]))). Record Foo_record : Type := { diff --git a/test-harness/src/snapshots/toolchain__literals into-fstar.snap b/test-harness/src/snapshots/toolchain__literals into-fstar.snap index 55c3c8e73..e93a5afdd 100644 --- a/test-harness/src/snapshots/toolchain__literals into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__literals into-fstar.snap @@ -64,7 +64,7 @@ let math_integers (x: Hax_lib.Int.t_Int) Hax_lib.Int.impl_Int__to_u8 (x + (x * x <: Hax_lib.Int.t_Int) <: Hax_lib.Int.t_Int) let panic_with_msg (_: Prims.unit) : Prims.unit = - Rust_primitives.Hax.never_to_any (Core.Panicking.panic_fmt (Core.Fmt.Rt.impl_2__new_const (mk_usize + Rust_primitives.Hax.never_to_any (Core.Panicking.panic_fmt (Core.Fmt.Rt.impl_1__new_const (mk_usize 1) (let list = ["with msg"] in FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 1); diff --git a/test-harness/src/snapshots/toolchain__mut-ref-functionalization into-fstar.snap b/test-harness/src/snapshots/toolchain__mut-ref-functionalization into-fstar.snap index ac5dff563..38d1d747b 100644 --- a/test-harness/src/snapshots/toolchain__mut-ref-functionalization into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__mut-ref-functionalization into-fstar.snap @@ -269,6 +269,7 @@ let k (Alloc.Vec.t_Vec u8 Alloc.Alloc.t_Global & u16 & Prims.unit & u64) class t_FooTrait (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_z_pre:v_Self -> Type0; f_z_post:v_Self -> v_Self -> Type0; f_z:x0: v_Self -> Prims.Pure v_Self (f_z_pre x0) (fun result -> f_z_post x0 result) diff --git a/test-harness/src/snapshots/toolchain__naming into-fstar.snap b/test-harness/src/snapshots/toolchain__naming into-fstar.snap index cae01d074..9ec3ce4a9 100644 --- a/test-harness/src/snapshots/toolchain__naming into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__naming into-fstar.snap @@ -33,20 +33,21 @@ open Core open FStar.Mul let debug (label value: u32) : Prims.unit = + let args:(u32 & u32) = label, value <: (u32 & u32) in + let args:t_Array Core.Fmt.Rt.t_Argument (mk_usize 2) = + let list = + [Core.Fmt.Rt.impl__new_display #u32 args._1; Core.Fmt.Rt.impl__new_display #u32 args._2] + in + FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 2); + Rust_primitives.Hax.array_of_list 2 list + in let _:Prims.unit = - Std.Io.Stdio.e_print (Core.Fmt.Rt.impl_2__new_v1 (mk_usize 3) + Std.Io.Stdio.e_print (Core.Fmt.Rt.impl_1__new_v1 (mk_usize 3) (mk_usize 2) (let list = ["["; "] a="; "\n"] in FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 3); Rust_primitives.Hax.array_of_list 3 list) - (let list = - [ - Core.Fmt.Rt.impl__new_display #u32 label <: Core.Fmt.Rt.t_Argument; - Core.Fmt.Rt.impl__new_display #u32 value <: Core.Fmt.Rt.t_Argument - ] - in - FStar.Pervasives.assert_norm (Prims.eq2 (List.Tot.length list) 2); - Rust_primitives.Hax.array_of_list 2 list) + args <: Core.Fmt.t_Arguments) in @@ -171,7 +172,9 @@ let reserved_names (v_val v_noeq v_of: u8) : u8 = (v_val +! v_noeq <: u8) +! v_o type t_Arity1 (v_T: Type0) = | Arity1 : v_T -> t_Arity1 v_T -class t_T1 (v_Self: Type0) = { __marker_trait_t_T1:Prims.unit } +class t_T1 (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self +} [@@ FStar.Tactics.Typeclasses.tcinstance] let impl_T1_for_Foo: t_T1 t_Foo = { __marker_trait = () } @@ -179,13 +182,17 @@ let impl_T1_for_Foo: t_T1 t_Foo = { __marker_trait = () } [@@ FStar.Tactics.Typeclasses.tcinstance] let impl_T1_for_tuple_Foo_u8: t_T1 (t_Foo & u8) = { __marker_trait = () } -class t_T2_for_a (v_Self: Type0) = { __marker_trait_t_T2_for_a:Prims.unit } +class t_T2_for_a (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self +} [@@ FStar.Tactics.Typeclasses.tcinstance] let impl_T2_ee_for_a_for_Arity1_of_tuple_Foo_u8: t_T2_for_a (t_Arity1 (t_Foo & u8)) = { __marker_trait = () } -class t_T3_ee_for_a (v_Self: Type0) = { __marker_trait_t_T3_ee_for_a:Prims.unit } +class t_T3_ee_for_a (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self +} [@@ FStar.Tactics.Typeclasses.tcinstance] let impl_T3_ee_e_for_a_for_Foo: t_T3_ee_for_a t_Foo = { __marker_trait = () } @@ -213,7 +220,10 @@ let construct_structs (a b: usize) : Prims.unit = let v_INHERENT_CONSTANT: usize = mk_usize 3 -class t_FooTrait (v_Self: Type0) = { f_ASSOCIATED_CONSTANT:usize } +class t_FooTrait (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; + f_ASSOCIATED_CONSTANT:usize +} let constants (#v_T: Type0) diff --git a/test-harness/src/snapshots/toolchain__side-effects into-fstar.snap b/test-harness/src/snapshots/toolchain__side-effects into-fstar.snap index a92a71909..0a676481d 100644 --- a/test-harness/src/snapshots/toolchain__side-effects into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__side-effects into-fstar.snap @@ -34,6 +34,7 @@ open Core open FStar.Mul class t_MyFrom (v_Self: Type0) (v_T: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_my_from_pre:v_T -> Type0; f_my_from_post:v_T -> v_Self -> Type0; f_my_from:x0: v_T -> Prims.Pure v_Self (f_my_from_pre x0) (fun result -> f_my_from_post x0 result) diff --git a/test-harness/src/snapshots/toolchain__traits into-fstar.snap b/test-harness/src/snapshots/toolchain__traits into-fstar.snap index 373243c11..fe5fe2c40 100644 --- a/test-harness/src/snapshots/toolchain__traits into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__traits into-fstar.snap @@ -32,13 +32,18 @@ module Traits.Block_size open Core open FStar.Mul -class t_BlockSizeUser (v_Self: Type0) = { f_BlockSize:Type0 } +class t_BlockSizeUser (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; + f_BlockSize:Type0 +} class t_ParBlocksSizeUser (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; [@@@ FStar.Tactics.Typeclasses.no_method]_super_5884559561557426095:t_BlockSizeUser v_Self } class t_BlockBackend (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; [@@@ FStar.Tactics.Typeclasses.no_method]_super_17422710415653782164:t_ParBlocksSizeUser v_Self; f_proc_block_pre:Alloc.Vec.t_Vec _ Alloc.Alloc.t_Global -> Type0; f_proc_block_post:Alloc.Vec.t_Vec _ Alloc.Alloc.t_Global -> Prims.unit -> Type0; @@ -52,9 +57,12 @@ module Traits.Default_traits_parameters open Core open FStar.Mul -class t_Bar (v_Self: Type0) (v_T: Type0) = { __marker_trait_t_Bar:Prims.unit } +class t_Bar (v_Self: Type0) (v_T: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self +} class t_Foo (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; [@@@ FStar.Tactics.Typeclasses.no_method]_super_7275791365833186636:t_Bar v_Self f_U; f_U:Type0 } @@ -65,7 +73,9 @@ module Traits.For_clauses.Issue_495_.Minimized_3_ open Core open FStar.Mul -class t_Trait (v_Self: Type0) = { __marker_trait_t_Trait:Prims.unit } +class t_Trait (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self +} [@@ FStar.Tactics.Typeclasses.tcinstance] let impl @@ -148,6 +158,7 @@ open Core open FStar.Mul class t_Foo (v_Self: Type0) (v_T: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_to_t_pre:v_Self -> Type0; f_to_t_post:v_Self -> v_T -> Type0; f_to_t:x0: v_Self -> Prims.Pure v_T (f_to_t_pre x0) (fun result -> f_to_t_post x0 result) @@ -164,9 +175,14 @@ module Traits.Impl_expr_in_goal open Core open FStar.Mul -class t_T1 (v_Self: Type0) = { f_Assoc:Type0 } +class t_T1 (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; + f_Assoc:Type0 +} -class t_T2 (v_Self: Type0) = { __marker_trait_t_T2:Prims.unit } +class t_T2 (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self +} [@@ FStar.Tactics.Typeclasses.tcinstance] let impl @@ -230,6 +246,7 @@ open Core open FStar.Mul class t_MyTrait (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_my_method_pre:v_Self -> Type0; f_my_method_post:v_Self -> Prims.unit -> Type0; f_my_method:x0: v_Self @@ -263,6 +280,7 @@ open FStar.Mul type t_Type (v_TypeArg: Type0) (v_ConstArg: usize) = { f_field:t_Array v_TypeArg v_ConstArg } class t_Trait (v_Self: Type0) (v_TypeArg: Type0) (v_ConstArg: usize) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_method_pre: #v_MethodTypeArg: Type0 -> v_MethodConstArg: usize -> @@ -425,6 +443,7 @@ let associated_function_caller () class t_SubTrait (v_Self: Type0) (v_TypeArg: Type0) (v_ConstArg: usize) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; [@@@ FStar.Tactics.Typeclasses.no_method]_super_15145771689388873921:t_Trait v_Self v_TypeArg v_ConstArg; @@ -442,6 +461,7 @@ type t_Bar (v_FooConst: usize) (v_FooType: Type0) = | Bar : t_Array v_FooType v_FooConst -> t_Bar v_FooConst v_FooType class t_Foo (v_Self: Type0) (v_FooConst: usize) (v_FooType: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_fun_pre: v_FunConst: usize -> #v_FunType: Type0 -> @@ -505,11 +525,13 @@ open Core open FStar.Mul class t_Trait1 (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_T:Type0; f_T_7969211799618487585:t_Trait1 f_T } class t_Trait2 (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; [@@@ FStar.Tactics.Typeclasses.no_method]_super_3259985701465885527:t_Trait1 v_Self; f_U:Type0 } @@ -530,6 +552,7 @@ open Core open FStar.Mul class t_PolyOp (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_op_pre:u32 -> u32 -> Type0; f_op_post:u32 -> u32 -> u32 -> Type0; f_op:x0: u32 -> x1: u32 -> Prims.Pure u32 (f_op_pre x0 x1) (fun result -> f_op_post x0 x1 result) @@ -567,6 +590,7 @@ open Core open FStar.Mul class t_SuperTrait (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; [@@@ FStar.Tactics.Typeclasses.no_method]_super_15837849249852401974:Core.Clone.t_Clone v_Self; f_function_of_super_trait_pre:v_Self -> Type0; f_function_of_super_trait_post:v_Self -> u32 -> Type0; @@ -588,6 +612,7 @@ let impl: t_SuperTrait i32 = type t_Struct = | Struct : t_Struct class t_Bar (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_bar_pre:v_Self -> Type0; f_bar_post:v_Self -> Prims.unit -> Type0; f_bar:x0: v_Self -> Prims.Pure Prims.unit (f_bar_pre x0) (fun result -> f_bar_post x0 result) @@ -650,6 +675,7 @@ let uuse_iimpl_trait (_: Prims.unit) : Prims.unit = () class t_Foo (v_Self: Type0) = { + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_AssocType:Type0; f_AssocType_1162045947544099865:t_SuperTrait f_AssocType; f_N:usize; From 1ca3abe861857539b371601547f7358afae470a9 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 1 Jul 2025 17:22:48 +0200 Subject: [PATCH 02/51] Don't overuse the `tcx` arena --- frontend/exporter/src/state.rs | 2 +- frontend/exporter/src/traits.rs | 5 +-- frontend/exporter/src/traits/resolution.rs | 16 ++++---- frontend/exporter/src/traits/utils.rs | 48 ++++++++-------------- frontend/exporter/src/types/hir.rs | 1 - frontend/exporter/src/types/ty.rs | 11 +++++ 6 files changed, 38 insertions(+), 45 deletions(-) diff --git a/frontend/exporter/src/state.rs b/frontend/exporter/src/state.rs index 18a5b749b..bf621c216 100644 --- a/frontend/exporter/src/state.rs +++ b/frontend/exporter/src/state.rs @@ -357,7 +357,7 @@ impl ImplInfos { .impl_trait_ref(did) .map(|trait_ref| trait_ref.instantiate_identity()) .sinto(s), - clauses: predicates_defined_on(tcx, did).predicates.sinto(s), + clauses: predicates_defined_on(tcx, did).as_ref().sinto(s), } } } diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index 377bef55c..619c21714 100644 --- a/frontend/exporter/src/traits.rs +++ b/frontend/exporter/src/traits.rs @@ -7,7 +7,7 @@ mod utils; #[cfg(feature = "rustc")] pub use utils::{ erase_and_norm, implied_predicates, predicates_defined_on, required_predicates, self_predicate, - ToPolyTraitRef, + Predicates, ToPolyTraitRef, }; #[cfg(feature = "rustc")] @@ -358,12 +358,11 @@ pub fn solve_item_implied_traits<'tcx, S: UnderOwnerState<'tcx>>( fn solve_item_traits_inner<'tcx, S: UnderOwnerState<'tcx>>( s: &S, generics: ty::GenericArgsRef<'tcx>, - predicates: ty::GenericPredicates<'tcx>, + predicates: utils::Predicates<'tcx>, ) -> Vec { let tcx = s.base().tcx; let typing_env = s.typing_env(); predicates - .predicates .iter() .map(|(clause, _span)| *clause) .filter_map(|clause| clause.as_trait_clause()) diff --git a/frontend/exporter/src/traits/resolution.rs b/frontend/exporter/src/traits/resolution.rs index 2b72db07d..ca3761145 100644 --- a/frontend/exporter/src/traits/resolution.rs +++ b/frontend/exporter/src/traits/resolution.rs @@ -11,9 +11,10 @@ use rustc_middle::traits::CodegenObligationError; use rustc_middle::ty::{self, *}; use rustc_trait_selection::traits::ImplSource; -use crate::{self_predicate, traits::utils::erase_and_norm}; - -use super::utils::{implied_predicates, normalize_bound_val, required_predicates, ToPolyTraitRef}; +use super::utils::{ + self, erase_and_norm, implied_predicates, normalize_bound_val, required_predicates, + self_predicate, ToPolyTraitRef, +}; #[derive(Debug, Clone)] pub enum PathChunk<'tcx> { @@ -179,7 +180,6 @@ fn initial_search_predicates<'tcx>( } predicates.extend( required_predicates(tcx, def_id, add_drop) - .predicates .iter() .map(|(clause, _span)| *clause) .filter_map(|clause| { @@ -204,7 +204,6 @@ fn parents_trait_predicates<'tcx>( ) -> Vec> { let self_trait_ref = pred.to_poly_trait_ref(); implied_predicates(tcx, pred.def_id(), add_drop) - .predicates .iter() .map(|(clause, _span)| *clause) // Substitute with the `self` args so that the clause makes sense in the @@ -342,8 +341,8 @@ impl<'tcx> PredicateSearcher<'tcx> { }; // The bounds that hold on the associated type. - let item_bounds = implied_predicates(tcx, alias_ty.def_id, self.add_drop) - .predicates + let item_bounds = implied_predicates(tcx, alias_ty.def_id, self.add_drop); + let item_bounds = item_bounds .iter() .map(|(clause, _span)| *clause) .filter_map(|pred| pred.as_trait_clause()) @@ -642,13 +641,12 @@ impl<'tcx> PredicateSearcher<'tcx> { pub fn resolve_predicates( &mut self, generics: GenericArgsRef<'tcx>, - predicates: GenericPredicates<'tcx>, + predicates: utils::Predicates<'tcx>, // Call back into hax-related code to display a nice warning. warn: &impl Fn(&str), ) -> Result>, String> { let tcx = self.tcx; predicates - .predicates .iter() .map(|(clause, _span)| *clause) .filter_map(|clause| clause.as_trait_clause()) diff --git a/frontend/exporter/src/traits/utils.rs b/frontend/exporter/src/traits/utils.rs index 20adc33e2..9e9cad39f 100644 --- a/frontend/exporter/src/traits/utils.rs +++ b/frontend/exporter/src/traits/utils.rs @@ -29,23 +29,21 @@ use rustc_hir::def::DefKind; use rustc_middle::ty::*; use rustc_span::def_id::DefId; -use rustc_span::DUMMY_SP; +use rustc_span::{Span, DUMMY_SP}; +use std::borrow::Cow; + +pub type Predicates<'tcx> = Cow<'tcx, [(Clause<'tcx>, Span)]>; /// Returns a list of type predicates for the definition with ID `def_id`, including inferred /// lifetime constraints. This is the basic list of predicates we use for essentially all items. -pub fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> GenericPredicates<'_> { - let mut result = tcx.explicit_predicates_of(def_id); +pub fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> Predicates<'_> { + let mut result = Cow::Borrowed(tcx.explicit_predicates_of(def_id).predicates); let inferred_outlives = tcx.inferred_outlives_of(def_id); if !inferred_outlives.is_empty() { - let inferred_outlives_iter = inferred_outlives - .iter() - .map(|(clause, span)| ((*clause).upcast(tcx), *span)); - result.predicates = tcx.arena.alloc_from_iter( - result - .predicates - .into_iter() - .copied() - .chain(inferred_outlives_iter), + result.to_mut().extend( + inferred_outlives + .iter() + .map(|(clause, span)| ((*clause).upcast(tcx), *span)), ); } result @@ -66,7 +64,7 @@ pub fn required_predicates<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, add_drop: bool, -) -> GenericPredicates<'tcx> { +) -> Predicates<'tcx> { use DefKind::*; let def_kind = tcx.def_kind(def_id); let mut predicates = match def_kind { @@ -103,9 +101,7 @@ pub fn required_predicates<'tcx>( .map(|ty| Binder::dummy(TraitRef::new(tcx, drop_trait, [ty]))) .map(|tref| tref.upcast(tcx)) .map(|clause| (clause, DUMMY_SP)); - predicates.predicates = tcx - .arena - .alloc_from_iter(predicates.predicates.iter().copied().chain(extra_bounds)); + predicates.to_mut().extend(extra_bounds); } } predicates @@ -134,36 +130,26 @@ pub fn implied_predicates<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, add_drop: bool, -) -> GenericPredicates<'tcx> { +) -> Predicates<'tcx> { use DefKind::*; let parent = tcx.opt_parent(def_id); match tcx.def_kind(def_id) { // We consider all predicates on traits to be outputs Trait | TraitAlias => predicates_defined_on(tcx, def_id), AssocTy if matches!(tcx.def_kind(parent.unwrap()), Trait) => { - let mut predicates = GenericPredicates { - parent, - // `skip_binder` is for the GAT `EarlyBinder` - predicates: tcx.explicit_item_bounds(def_id).skip_binder(), - ..GenericPredicates::default() - }; + // `skip_binder` is for the GAT `EarlyBinder` + let mut predicates = Cow::Borrowed(tcx.explicit_item_bounds(def_id).skip_binder()); if add_drop { // Add a `Drop` bound to the assoc item. let drop_trait = tcx.lang_items().drop_trait().unwrap(); let ty = Ty::new_projection(tcx, def_id, GenericArgs::identity_for_item(tcx, def_id)); let tref = Binder::dummy(TraitRef::new(tcx, drop_trait, [ty])); - predicates.predicates = tcx.arena.alloc_from_iter( - predicates - .predicates - .iter() - .copied() - .chain([(tref.upcast(tcx), DUMMY_SP)]), - ); + predicates.to_mut().push((tref.upcast(tcx), DUMMY_SP)); } predicates } - _ => GenericPredicates::default(), + _ => Predicates::default(), } } diff --git a/frontend/exporter/src/types/hir.rs b/frontend/exporter/src/types/hir.rs index 2a80a7837..669063f26 100644 --- a/frontend/exporter/src/types/hir.rs +++ b/frontend/exporter/src/types/hir.rs @@ -830,7 +830,6 @@ fn region_bounds_at_current_owner<'tcx, S: UnderOwnerState<'tcx>>(s: &S) -> Gene .instantiate_identity() } else { predicates_defined_on(tcx, s.owner_id()) - .predicates .iter() .map(|(x, _span)| x) .copied() diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index 49c9f2651..34e3e0e69 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -1337,6 +1337,17 @@ pub struct GenericPredicates { pub predicates: Vec<(Clause, Span)>, } +#[cfg(feature = "rustc")] +impl<'tcx, S: UnderOwnerState<'tcx>> SInto + for crate::traits::Predicates<'tcx> +{ + fn sinto(&self, s: &S) -> GenericPredicates { + GenericPredicates { + predicates: self.as_ref().sinto(s), + } + } +} + #[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>, T1, T2> SInto> for ty::Binder<'tcx, T1> where From 7dac8486961f492e736eca3a49e075888a3b421e Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 2 Jul 2025 16:56:58 +0200 Subject: [PATCH 03/51] Add an explicit `Self: Trait` clause to trait assoc items This way, the special `ImplExpr::SelfImpl` is only valid within a trait declaration. --- frontend/exporter/src/traits.rs | 7 ++++--- frontend/exporter/src/traits/resolution.rs | 20 ++++++++++++++---- frontend/exporter/src/traits/utils.rs | 5 +++++ .../toolchain__traits into-fstar.snap | 21 ++++++++++++++----- 4 files changed, 41 insertions(+), 12 deletions(-) diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index 619c21714..06c53f42f 100644 --- a/frontend/exporter/src/traits.rs +++ b/frontend/exporter/src/traits.rs @@ -290,7 +290,9 @@ pub fn translate_item_ref<'tcx, S: UnderOwnerState<'tcx>>( let num_trait_generics = trait_ref.generic_args.len(); generic_args.drain(0..num_trait_generics); let num_trait_trait_clauses = trait_ref.impl_exprs.len(); - impl_exprs.drain(0..num_trait_trait_clauses); + // Associated items take a `Self` clause as first clause, we skip that one too. Note: that + // clause is the same as `tinfo`. + impl_exprs.drain(0..num_trait_trait_clauses + 1); } let content = ItemRefContents { @@ -386,7 +388,6 @@ pub fn self_clause_for_item<'tcx, S: UnderOwnerState<'tcx>>( def_id: RDefId, generics: rustc_middle::ty::GenericArgsRef<'tcx>, ) -> Option { - use rustc_middle::ty::EarlyBinder; let tcx = s.base().tcx; let tr_def_id = tcx.trait_of_item(def_id)?; @@ -394,7 +395,7 @@ pub fn self_clause_for_item<'tcx, S: UnderOwnerState<'tcx>>( let self_pred = self_predicate(tcx, tr_def_id); // Substitute to be in the context of the current item. let generics = generics.truncate_to(tcx, tcx.generics_of(tr_def_id)); - let self_pred = EarlyBinder::bind(self_pred).instantiate(tcx, generics); + let self_pred = ty::EarlyBinder::bind(self_pred).instantiate(tcx, generics); // Resolve Some(solve_trait(s, self_pred)) diff --git a/frontend/exporter/src/traits/resolution.rs b/frontend/exporter/src/traits/resolution.rs index ca3761145..6ac0989e3 100644 --- a/frontend/exporter/src/traits/resolution.rs +++ b/frontend/exporter/src/traits/resolution.rs @@ -154,6 +154,7 @@ fn initial_search_predicates<'tcx>( tcx: TyCtxt<'tcx>, def_id: rustc_span::def_id::DefId, add_drop: bool, + include_self_pred: bool, predicates: &mut Vec>, pred_id: &mut usize, ) { @@ -165,11 +166,22 @@ fn initial_search_predicates<'tcx>( use DefKind::*; match tcx.def_kind(def_id) { // These inherit some predicates from their parent. - AssocTy | AssocFn | AssocConst | Closure | Ctor(..) | Variant => { + dk @ (AssocTy | AssocFn | AssocConst | Closure | Ctor(..) | Variant) => { let parent = tcx.parent(def_id); - acc_predicates(tcx, parent, add_drop, predicates, pred_id); + // Hack: we don't support GATs well so for now we let assoc types refer to the + // implicit trait `Self` clause. Other associated items get an explicit `Self: + // Trait` clause passed to them so they don't need that. + let include_self_pred = include_self_pred && matches!(dk, AssocTy); + acc_predicates( + tcx, + parent, + add_drop, + include_self_pred, + predicates, + pred_id, + ); } - Trait | TraitAlias => { + Trait | TraitAlias if include_self_pred => { let self_pred = self_predicate(tcx, def_id).upcast(tcx); predicates.push(AnnotatedTraitPred { origin: BoundPredicateOrigin::SelfPred, @@ -192,7 +204,7 @@ fn initial_search_predicates<'tcx>( } let mut predicates = vec![]; - acc_predicates(tcx, def_id, add_drop, &mut predicates, &mut 0); + acc_predicates(tcx, def_id, add_drop, true, &mut predicates, &mut 0); predicates } diff --git a/frontend/exporter/src/traits/utils.rs b/frontend/exporter/src/traits/utils.rs index 9e9cad39f..3d469eb92 100644 --- a/frontend/exporter/src/traits/utils.rs +++ b/frontend/exporter/src/traits/utils.rs @@ -86,6 +86,11 @@ pub fn required_predicates<'tcx>( // `predicates_defined_on` ICEs on other def kinds. _ => Default::default(), }; + // For associated items in trait definitions, we add an explicit `Self: Trait` clause. + if let Some(trait_def_id) = tcx.trait_of_item(def_id) { + let self_clause = self_predicate(tcx, trait_def_id).upcast(tcx); + predicates.to_mut().insert(0, (self_clause, DUMMY_SP)); + } if add_drop { // Add a `T: Drop` bound for every generic, unless the current trait is `Drop` itself, or // `Sized`. diff --git a/test-harness/src/snapshots/toolchain__traits into-fstar.snap b/test-harness/src/snapshots/toolchain__traits into-fstar.snap index fe5fe2c40..f0132d6a7 100644 --- a/test-harness/src/snapshots/toolchain__traits into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__traits into-fstar.snap @@ -687,9 +687,18 @@ class t_Foo (v_Self: Type0) = { f_method_f_post:v_Self -> Prims.unit -> Type0; f_method_f:x0: v_Self -> Prims.Pure Prims.unit (f_method_f_pre x0) (fun result -> f_method_f_post x0 result); - f_assoc_type_pre:{| i2: Core.Marker.t_Copy f_AssocType |} -> f_AssocType -> Type0; - f_assoc_type_post:{| i2: Core.Marker.t_Copy f_AssocType |} -> f_AssocType -> Prims.unit -> Type0; - f_assoc_type:{| i2: Core.Marker.t_Copy f_AssocType |} -> x0: f_AssocType + f_assoc_type_pre: + {| i2: Core.Marker.t_Copy v_5081411602995720689.f_AssocType |} -> + v_5081411602995720689.f_AssocType + -> Type0; + f_assoc_type_post: + {| i2: Core.Marker.t_Copy v_5081411602995720689.f_AssocType |} -> + v_5081411602995720689.f_AssocType -> + Prims.unit + -> Type0; + f_assoc_type: + {| i2: Core.Marker.t_Copy v_5081411602995720689.f_AssocType |} -> + x0: v_5081411602995720689.f_AssocType -> Prims.Pure Prims.unit (f_assoc_type_pre #i2 x0) (fun result -> f_assoc_type_post #i2 x0 result) @@ -698,9 +707,11 @@ class t_Foo (v_Self: Type0) = { class t_Lang (v_Self: Type0) = { f_Var:Type0; f_s_pre:v_Self -> i32 -> Type0; - f_s_post:v_Self -> i32 -> (v_Self & f_Var) -> Type0; + f_s_post:v_Self -> i32 -> (v_Self & v_178762381425797165.f_Var) -> Type0; f_s:x0: v_Self -> x1: i32 - -> Prims.Pure (v_Self & f_Var) (f_s_pre x0 x1) (fun result -> f_s_post x0 x1 result) + -> Prims.Pure (v_Self & v_178762381425797165.f_Var) + (f_s_pre x0 x1) + (fun result -> f_s_post x0 x1 result) } let f (#v_T: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] i1: t_Foo v_T) (x: v_T) : Prims.unit = From 6471ff267d4a812f9453ef3bc0c875ea1d6e8572 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 3 Jul 2025 17:04:33 +0200 Subject: [PATCH 04/51] Don't add `Drop` clauses to some more marker traits --- frontend/exporter/src/traits/utils.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/frontend/exporter/src/traits/utils.rs b/frontend/exporter/src/traits/utils.rs index 3d469eb92..a8e561d8c 100644 --- a/frontend/exporter/src/traits/utils.rs +++ b/frontend/exporter/src/traits/utils.rs @@ -27,6 +27,7 @@ //! benefit of reducing the size of signatures. Moreover, the rules on which bounds are required vs //! implied are subtle. We may change this if this proves to be a problem. use rustc_hir::def::DefKind; +use rustc_hir::LangItem; use rustc_middle::ty::*; use rustc_span::def_id::DefId; use rustc_span::{Span, DUMMY_SP}; @@ -92,11 +93,21 @@ pub fn required_predicates<'tcx>( predicates.to_mut().insert(0, (self_clause, DUMMY_SP)); } if add_drop { - // Add a `T: Drop` bound for every generic, unless the current trait is `Drop` itself, or - // `Sized`. - let drop_trait = tcx.lang_items().drop_trait().unwrap(); - let sized_trait = tcx.lang_items().sized_trait().unwrap(); - if def_id != drop_trait && def_id != sized_trait { + // Add a `T: Drop` bound for every generic, unless the current trait is `Drop` itself, or a + // built-in marker trait that we know doesn't need the bound. + let lang_item = tcx.as_lang_item(def_id); + if !matches!( + lang_item, + Some( + LangItem::Drop + | LangItem::Sized + | LangItem::MetaSized + | LangItem::PointeeSized + | LangItem::DiscriminantKind + | LangItem::PointeeTrait + ) + ) { + let drop_trait = tcx.lang_items().drop_trait().unwrap(); let extra_bounds = tcx .generics_of(def_id) .own_params From ae0f212cd240065b339a3f0e62c33b352d976b43 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 3 Jul 2025 22:44:09 +0200 Subject: [PATCH 05/51] Normalize projections before translating them --- frontend/exporter/src/traits.rs | 4 ++-- frontend/exporter/src/traits/utils.rs | 19 ++++++++++++++++++- frontend/exporter/src/types/ty.rs | 12 +++++++++++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index 06c53f42f..3c00f1642 100644 --- a/frontend/exporter/src/traits.rs +++ b/frontend/exporter/src/traits.rs @@ -6,8 +6,8 @@ mod resolution; mod utils; #[cfg(feature = "rustc")] pub use utils::{ - erase_and_norm, implied_predicates, predicates_defined_on, required_predicates, self_predicate, - Predicates, ToPolyTraitRef, + erase_and_norm, erase_free_regions, implied_predicates, normalize, predicates_defined_on, + required_predicates, self_predicate, Predicates, ToPolyTraitRef, }; #[cfg(feature = "rustc")] diff --git a/frontend/exporter/src/traits/utils.rs b/frontend/exporter/src/traits/utils.rs index a8e561d8c..cf0d94162 100644 --- a/frontend/exporter/src/traits/utils.rs +++ b/frontend/exporter/src/traits/utils.rs @@ -169,10 +169,27 @@ pub fn implied_predicates<'tcx>( } } +/// Normalize a value. +pub fn normalize<'tcx, T>(tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>, value: T) -> T +where + T: TypeFoldable> + Copy, +{ + use rustc_infer::infer::TyCtxtInferExt; + use rustc_middle::traits::ObligationCause; + use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); + infcx + .at(&ObligationCause::dummy(), param_env) + .query_normalize(value) + // We ignore the generated outlives relations. Unsure what we should do with them. + .map(|x| x.value) + .unwrap_or(value) +} + /// Erase free regions from the given value. Largely copied from `tcx.erase_regions`, but also /// erases bound regions that are bound outside `value`, so we can call this function inside a /// `Binder`. -fn erase_free_regions<'tcx, T>(tcx: TyCtxt<'tcx>, value: T) -> T +pub fn erase_free_regions<'tcx, T>(tcx: TyCtxt<'tcx>, value: T) -> T where T: TypeFoldable>, { diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index 34e3e0e69..bfc1fe3e9 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -804,7 +804,17 @@ impl Alias { alias_ty: &ty::AliasTy<'tcx>, ) -> TyKind { let tcx = s.base().tcx; + let typing_env = s.typing_env(); use rustc_type_ir::AliasTyKind as RustAliasKind; + + // Try to normalize the alias first. + let ty = ty::Ty::new_alias(tcx, *alias_kind, *alias_ty); + let ty = crate::traits::normalize(tcx, typing_env, ty); + let ty::Alias(alias_kind, alias_ty) = ty.kind() else { + let ty: Ty = ty.sinto(s); + return ty.kind().clone(); + }; + let kind = match alias_kind { RustAliasKind::Projection => { let trait_ref = alias_ty.trait_ref(tcx); @@ -820,7 +830,7 @@ impl Alias { // yet we dont have a binder around (could even be several). Binding this correctly // is therefore difficult. Since our trait resolution ignores lifetimes anyway, we // just erase them. See also https://github.com/hacspec/hax/issues/747. - let trait_ref = crate::traits::erase_and_norm(tcx, s.typing_env(), trait_ref); + let trait_ref = crate::traits::erase_free_regions(tcx, trait_ref); AliasKind::Projection { assoc_item: tcx.associated_item(alias_ty.def_id).sinto(s), impl_expr: solve_trait(s, ty::Binder::dummy(trait_ref)), From 8c92b5073f873d3bbd51120b646da058d114fa66 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 3 Jul 2025 22:44:46 +0200 Subject: [PATCH 06/51] Resolve assoc ty predicates in builtin `ImplExpr`s --- frontend/exporter/src/sinto.rs | 8 ++++++++ frontend/exporter/src/traits.rs | 2 +- frontend/exporter/src/traits/resolution.rs | 11 +++++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/frontend/exporter/src/sinto.rs b/frontend/exporter/src/sinto.rs index 15d65f66b..8363ecb78 100644 --- a/frontend/exporter/src/sinto.rs +++ b/frontend/exporter/src/sinto.rs @@ -65,6 +65,14 @@ impl, R: SInto> SInto for (L, R) } } +impl, B: SInto, C: SInto> SInto + for (A, B, C) +{ + fn sinto(&self, s: &S) -> (AA, BB, CC) { + (self.0.sinto(s), self.1.sinto(s), self.2.sinto(s)) + } +} + impl> SInto> for Option { fn sinto(&self, s: &S) -> Option { self.as_ref().map(|x| x.sinto(s)) diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index 3c00f1642..6879130f6 100644 --- a/frontend/exporter/src/traits.rs +++ b/frontend/exporter/src/traits.rs @@ -140,7 +140,7 @@ pub enum ImplExprAtom { /// FnOnce`. impl_exprs: Vec, /// The values of the associated types for this trait. - types: Vec<(DefId, Ty)>, + types: Vec<(DefId, Ty, Vec)>, }, /// An error happened while resolving traits. Error(String), diff --git a/frontend/exporter/src/traits/resolution.rs b/frontend/exporter/src/traits/resolution.rs index 6ac0989e3..a13291898 100644 --- a/frontend/exporter/src/traits/resolution.rs +++ b/frontend/exporter/src/traits/resolution.rs @@ -89,7 +89,7 @@ pub enum ImplExprAtom<'tcx> { /// FnOnce`. impl_exprs: Vec>, /// The values of the associated types for this trait. - types: Vec<(DefId, Ty<'tcx>)>, + types: Vec<(DefId, Ty<'tcx>, Vec>)>, }, /// An error happened while resolving traits. Error(String), @@ -495,7 +495,14 @@ impl<'tcx> PredicateSearcher<'tcx> { return None; } } - Some((assoc.def_id, ty)) + let impl_exprs = self + .resolve_item_implied_predicates( + assoc.def_id, + erased_tref.skip_binder().args, + warn, + ) + .ok()?; + Some((assoc.def_id, ty, impl_exprs)) }) .collect(); ImplExprAtom::Builtin { From 407c12198a8117710c4670f6d2836091348183d5 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 20 Jun 2025 02:09:12 +0200 Subject: [PATCH 07/51] Don't use `SInto` derive for `FullDefKind` --- frontend/exporter/src/types/new/full_def.rs | 508 +++++++++++--------- 1 file changed, 288 insertions(+), 220 deletions(-) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 91a3e49a9..9d41f8ddf 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -53,9 +53,9 @@ where let kind; match def_id.promoted_id() { None => { - let def_kind = get_def_kind(tcx, rust_def_id); - kind = def_kind.sinto(&state_with_id); + kind = translate_full_def_kind(s, rust_def_id); + let def_kind = get_def_kind(tcx, rust_def_id); source_span = rust_def_id.as_local().map(|ldid| tcx.source_span(ldid)); attributes = get_def_attrs(tcx, rust_def_id, def_kind).sinto(s); visibility = get_def_visibility(tcx, rust_def_id, def_kind); @@ -175,75 +175,43 @@ pub struct ParamEnv { } /// Imbues [`rustc_hir::def::DefKind`] with a lot of extra information. -/// Important: the `owner_id()` must be the id of this definition. -#[derive(AdtInto)] -#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_hir::def::DefKind, state: S as s, where Body: IsBody + TypeMappable)] #[derive_group(Serializers)] #[derive(Clone, Debug, JsonSchema)] pub enum FullDefKind { // Types /// Refers to the struct definition, [`DefKind::Ctor`] refers to its constructor if it exists. Struct { - #[value(get_param_env(s, s.owner_id()))] param_env: ParamEnv, - #[value(s.base().tcx.adt_def(s.owner_id()).sinto(s))] def: AdtDef, /// MIR body of the builtin `drop` impl. - #[value(drop_glue_shim(s.base().tcx, s.owner_id()).and_then(|body| Body::from_mir(s, body)))] drop_glue: Option, }, Union { - #[value(get_param_env(s, s.owner_id()))] param_env: ParamEnv, - #[value(s.base().tcx.adt_def(s.owner_id()).sinto(s))] def: AdtDef, /// MIR body of the builtin `drop` impl. - #[value(drop_glue_shim(s.base().tcx, s.owner_id()).and_then(|body| Body::from_mir(s, body)))] drop_glue: Option, }, Enum { - #[value(get_param_env(s, s.owner_id()))] param_env: ParamEnv, - #[value(s.base().tcx.adt_def(s.owner_id()).sinto(s))] def: AdtDef, /// MIR body of the builtin `drop` impl. - #[value(drop_glue_shim(s.base().tcx, s.owner_id()).and_then(|body| Body::from_mir(s, body)))] drop_glue: Option, }, /// Type alias: `type Foo = Bar;` TyAlias { - #[value(get_param_env(s, s.owner_id()))] param_env: ParamEnv, /// `Some` if the item is in the local crate. - #[value(s.base().tcx.hir_get_if_local(s.owner_id()).map(|node| { - let rustc_hir::Node::Item(item) = node else { unreachable!() }; - let rustc_hir::ItemKind::TyAlias(_, _generics, ty) = &item.kind else { unreachable!() }; - let mut s = State::from_under_owner(s); - s.base.ty_alias_mode = true; - ty.sinto(&s) - }))] ty: Option, }, /// Type from an `extern` block. ForeignTy, /// Associated type: `trait MyTrait { type Assoc; }` AssocTy { - #[value(s.base().tcx.parent(s.owner_id()).sinto(s))] parent: DefId, - #[value(get_param_env(s, s.owner_id()))] param_env: ParamEnv, - #[value(implied_predicates(s.base().tcx, s.owner_id(), s.base().options.resolve_drop_bounds).sinto(s))] implied_predicates: GenericPredicates, - #[value(s.base().tcx.associated_item(s.owner_id()).sinto(s))] associated_item: AssocItem, - #[value({ - let tcx = s.base().tcx; - if tcx.defaultness(s.owner_id()).has_value() { - Some(tcx.type_of(s.owner_id()).instantiate_identity().sinto(s)) - } else { - None - } - })] value: Option, }, /// Opaque type, aka `impl Trait`. @@ -251,42 +219,20 @@ pub enum FullDefKind { // Traits Trait { - #[value(get_param_env(s, s.owner_id()))] param_env: ParamEnv, - #[value(implied_predicates(s.base().tcx, s.owner_id(), s.base().options.resolve_drop_bounds).sinto(s))] implied_predicates: GenericPredicates, /// The special `Self: Trait` clause. - #[value(get_self_predicate(s))] self_predicate: TraitPredicate, /// Associated items, in definition order. - #[value( - s - .base() - .tcx - .associated_items(s.owner_id()) - .in_definition_order() - .map(|assoc| { - let def_id = assoc.def_id.sinto(s); - (assoc.sinto(s), def_id.full_def(s)) - }) - .collect::>() - )] items: Vec<(AssocItem, Arc>)>, }, /// Trait alias: `trait IntIterator = Iterator;` TraitAlias { - #[value(get_param_env(s, s.owner_id()))] param_env: ParamEnv, - #[value(implied_predicates(s.base().tcx, s.owner_id(), s.base().options.resolve_drop_bounds).sinto(s))] implied_predicates: GenericPredicates, /// The special `Self: Trait` clause. - #[value(get_self_predicate(s))] self_predicate: TraitPredicate, }, - #[custom_arm( - // Returns `TraitImpl` or `InherentImpl`. - RDefKind::Impl { .. } => get_impl_contents(s), - )] TraitImpl { param_env: ParamEnv, /// The trait that is implemented by this impl block. @@ -300,7 +246,6 @@ pub enum FullDefKind { /// Associated items, in the order of the trait declaration. Includes defaulted items. items: Vec>, }, - #[disable_mapping] InherentImpl { param_env: ParamEnv, /// The type to which this block applies. @@ -311,33 +256,21 @@ pub enum FullDefKind { // Functions Fn { - #[value(get_param_env(s, s.owner_id()))] param_env: ParamEnv, - #[value(s.base().tcx.codegen_fn_attrs(s.owner_id()).inline.sinto(s))] inline: InlineAttr, - #[value(s.base().tcx.constness(s.owner_id()) == rustc_hir::Constness::Const)] is_const: bool, - #[value(s.base().tcx.fn_sig(s.owner_id()).instantiate_identity().sinto(s))] sig: PolyFnSig, - #[value(Body::body(s.owner_id(), s))] body: Option, }, /// Associated function: `impl MyStruct { fn associated() {} }` or `trait Foo { fn associated() /// {} }` AssocFn { - #[value(s.base().tcx.parent(s.owner_id()).sinto(s))] parent: DefId, - #[value(get_param_env(s, s.owner_id()))] param_env: ParamEnv, - #[value(s.base().tcx.associated_item(s.owner_id()).sinto(s))] associated_item: AssocItem, - #[value(s.base().tcx.codegen_fn_attrs(s.owner_id()).inline.sinto(s))] inline: InlineAttr, - #[value(s.base().tcx.constness(s.owner_id()) == rustc_hir::Constness::Const)] is_const: bool, - #[value(get_method_sig(s).sinto(s))] sig: PolyFnSig, - #[value(Body::body(s.owner_id(), s))] body: Option, }, /// A closure, coroutine, or coroutine-closure. @@ -348,79 +281,49 @@ pub enum FullDefKind { /// The enclosing item. Note: this item could itself be a closure; to get the generics, you /// might have to recurse through several layers of parents until you find a function or /// constant. - #[value(s.base().tcx.parent(s.owner_id()).sinto(s))] parent: DefId, - #[value(s.base().tcx.constness(s.owner_id()) == rustc_hir::Constness::Const)] is_const: bool, - #[value({ - let closure_ty = s.base().tcx.type_of(s.owner_id()).instantiate_identity(); - let ty::TyKind::Closure(_, args) = closure_ty.kind() else { unreachable!() }; - ClosureArgs::sfrom(s, s.owner_id(), args.as_closure()) - })] args: ClosureArgs, /// For `FnMut`&`Fn` closures: the MIR for the `call_once` method; it simply calls /// `call_mut`. - #[value({ - let tcx = s.base().tcx; - let closure_ty = tcx.type_of(s.owner_id()).instantiate_identity(); - let opt_body = closure_once_shim(tcx, closure_ty); - opt_body.and_then(|body| Body::from_mir(s, body)) - })] once_shim: Option, /// MIR body of the builtin `drop` impl. - #[value(drop_glue_shim(s.base().tcx, s.owner_id()).and_then(|body| Body::from_mir(s, body)))] drop_glue: Option, }, // Constants Const { - #[value(get_param_env(s, s.owner_id()))] param_env: ParamEnv, - #[value(s.base().tcx.type_of(s.owner_id()).instantiate_identity().sinto(s))] ty: Ty, - #[value(Body::body(s.owner_id(), s))] body: Option, }, /// Associated constant: `trait MyTrait { const ASSOC: usize; }` AssocConst { - #[value(s.base().tcx.parent(s.owner_id()).sinto(s))] parent: DefId, - #[value(get_param_env(s, s.owner_id()))] param_env: ParamEnv, - #[value(s.base().tcx.associated_item(s.owner_id()).sinto(s))] associated_item: AssocItem, - #[value(s.base().tcx.type_of(s.owner_id()).instantiate_identity().sinto(s))] ty: Ty, - #[value(Body::body(s.owner_id(), s))] body: Option, }, /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]` AnonConst { - #[value(get_param_env(s, s.owner_id()))] param_env: ParamEnv, - #[value(s.base().tcx.type_of(s.owner_id()).instantiate_identity().sinto(s))] ty: Ty, - #[value(Body::body(s.owner_id(), s))] body: Option, }, /// An inline constant, e.g. `const { 1 + 2 }` InlineConst { - #[value(get_param_env(s, s.owner_id()))] param_env: ParamEnv, - #[value(s.base().tcx.type_of(s.owner_id()).instantiate_identity().sinto(s))] ty: Ty, - #[value(Body::body(s.owner_id(), s))] body: Option, }, /// A promoted constant, e.g. `&(1 + 2)` - #[disable_mapping] PromotedConst { param_env: ParamEnv, ty: Ty, body: Body, }, Static { - #[value(get_param_env(s, s.owner_id()))] param_env: ParamEnv, /// Whether it's a `unsafe static`, `safe static` (inside extern only) or just a `static`. safety: Safety, @@ -428,9 +331,7 @@ pub enum FullDefKind { mutability: Mutability, /// Whether it's an anonymous static generated for nested allocations. nested: bool, - #[value(s.base().tcx.type_of(s.owner_id()).instantiate_identity().sinto(s))] ty: Ty, - #[value(Body::body(s.owner_id(), s))] body: Option, }, @@ -438,12 +339,10 @@ pub enum FullDefKind { ExternCrate, Use, Mod { - #[value(get_mod_children(s.base().tcx, s.owner_id()).sinto(s))] items: Vec<(Option, DefId)>, }, /// An `extern` block. ForeignMod { - #[value(get_foreign_mod_children(s.base().tcx, s.owner_id()).sinto(s))] items: Vec, }, @@ -459,7 +358,6 @@ pub enum FullDefKind { /// Refers to the variant definition, [`DefKind::Ctor`] refers to its constructor if it exists. Variant, /// The constructor function of a tuple/unit struct or tuple/unit enum variant. - #[custom_arm(RDefKind::Ctor(ctor_of, _) => get_ctor_contents(s, ctor_of.sinto(s)),)] Ctor { adt_def_id: DefId, ctor_of: CtorOf, @@ -482,6 +380,292 @@ pub enum FullDefKind { SyntheticCoroutineBody, } +#[cfg(feature = "rustc")] +fn translate_full_def_kind<'tcx, S, Body>(s: &S, def_id: RDefId) -> FullDefKind +where + S: BaseState<'tcx>, + Body: IsBody + TypeMappable, +{ + let s = &with_owner_id(s.base(), (), (), def_id); + let tcx = s.base().tcx; + match get_def_kind(tcx, def_id) { + RDefKind::Struct { .. } => FullDefKind::Struct { + param_env: get_param_env(s, def_id), + def: tcx.adt_def(def_id).sinto(s), + drop_glue: drop_glue_shim(tcx, def_id).and_then(|body| Body::from_mir(s, body)), + }, + RDefKind::Union { .. } => FullDefKind::Union { + param_env: get_param_env(s, def_id), + def: tcx.adt_def(def_id).sinto(s), + drop_glue: drop_glue_shim(tcx, def_id).and_then(|body| Body::from_mir(s, body)), + }, + RDefKind::Enum { .. } => FullDefKind::Enum { + param_env: get_param_env(s, def_id), + def: tcx.adt_def(def_id).sinto(s), + drop_glue: drop_glue_shim(tcx, def_id).and_then(|body| Body::from_mir(s, body)), + }, + RDefKind::TyAlias { .. } => FullDefKind::TyAlias { + param_env: get_param_env(s, def_id), + ty: tcx.hir_get_if_local(def_id).map(|node| { + let rustc_hir::Node::Item(item) = node else { + unreachable!() + }; + let rustc_hir::ItemKind::TyAlias(_, _generics, ty) = &item.kind else { + unreachable!() + }; + let mut s = State::from_under_owner(s); + s.base.ty_alias_mode = true; + ty.sinto(&s) + }), + }, + RDefKind::ForeignTy => FullDefKind::ForeignTy, + RDefKind::AssocTy { .. } => FullDefKind::AssocTy { + parent: tcx.parent(def_id).sinto(s), + param_env: get_param_env(s, def_id), + implied_predicates: implied_predicates( + tcx, + def_id, + s.base().options.resolve_drop_bounds, + ) + .sinto(s), + associated_item: tcx.associated_item(def_id).sinto(s), + value: if tcx.defaultness(def_id).has_value() { + Some(tcx.type_of(def_id).instantiate_identity().sinto(s)) + } else { + None + }, + }, + RDefKind::OpaqueTy => FullDefKind::OpaqueTy, + RDefKind::Trait { .. } => FullDefKind::Trait { + param_env: get_param_env(s, def_id), + implied_predicates: implied_predicates( + tcx, + def_id, + s.base().options.resolve_drop_bounds, + ) + .sinto(s), + self_predicate: get_self_predicate(s), + items: tcx + .associated_items(def_id) + .in_definition_order() + .map(|assoc| { + let def_id = assoc.def_id.sinto(s); + (assoc.sinto(s), def_id.full_def(s)) + }) + .collect::>(), + }, + RDefKind::TraitAlias { .. } => FullDefKind::TraitAlias { + param_env: get_param_env(s, def_id), + implied_predicates: implied_predicates( + tcx, + def_id, + s.base().options.resolve_drop_bounds, + ) + .sinto(s), + self_predicate: get_self_predicate(s), + }, + RDefKind::Impl { .. } => { + use std::collections::HashMap; + let param_env = get_param_env(s, def_id); + match tcx.impl_subject(def_id).instantiate_identity() { + ty::ImplSubject::Inherent(ty) => { + let items = tcx + .associated_items(def_id) + .in_definition_order() + .map(|assoc| { + let def_id = assoc.def_id.sinto(s); + (assoc.sinto(s), def_id.full_def(s)) + }) + .collect::>(); + FullDefKind::InherentImpl { + param_env, + ty: ty.sinto(s), + items, + } + } + ty::ImplSubject::Trait(trait_ref) => { + // Also record the polarity. + let polarity = tcx.impl_polarity(def_id); + let trait_pred = TraitPredicate { + trait_ref: trait_ref.sinto(s), + is_positive: matches!(polarity, ty::ImplPolarity::Positive), + }; + // Impl exprs required by the trait. + let required_impl_exprs = + solve_item_implied_traits(s, trait_ref.def_id, trait_ref.args); + + let mut item_map: HashMap = tcx + .associated_items(def_id) + .in_definition_order() + .map(|assoc| (assoc.trait_item_def_id.unwrap(), assoc)) + .collect(); + let items = tcx + .associated_items(trait_ref.def_id) + .in_definition_order() + .map(|decl_assoc| { + let decl_def_id = decl_assoc.def_id; + let decl_def = decl_def_id.sinto(s).full_def(s); + // Impl exprs required by the item. + let required_impl_exprs; + let value = match item_map.remove(&decl_def_id) { + Some(impl_assoc) => { + required_impl_exprs = { + let item_args = ty::GenericArgs::identity_for_item( + tcx, + impl_assoc.def_id, + ); + // Subtlety: we have to add the GAT arguments (if any) to the trait ref arguments. + let args = + item_args.rebase_onto(tcx, def_id, trait_ref.args); + let state_with_id = + with_owner_id(s.base(), (), (), impl_assoc.def_id); + solve_item_implied_traits(&state_with_id, decl_def_id, args) + }; + + ImplAssocItemValue::Provided { + def: impl_assoc.def_id.sinto(s).full_def(s), + is_override: decl_assoc.defaultness(tcx).has_value(), + } + } + None => { + required_impl_exprs = if tcx + .generics_of(decl_def_id) + .is_own_empty() + { + // Non-GAT case. + let item_args = + ty::GenericArgs::identity_for_item(tcx, decl_def_id); + let args = + item_args.rebase_onto(tcx, def_id, trait_ref.args); + let state_with_id = with_owner_id(s.base(), (), (), def_id); + solve_item_implied_traits(&state_with_id, decl_def_id, args) + } else { + // FIXME: For GATs, we need a param_env that has the arguments of + // the impl plus those of the associated type, but there's no + // def_id with that param_env. + vec![] + }; + match decl_assoc.kind { + ty::AssocKind::Type { .. } => { + let ty = tcx + .type_of(decl_def_id) + .instantiate(tcx, trait_ref.args) + .sinto(s); + ImplAssocItemValue::DefaultedTy { ty } + } + ty::AssocKind::Fn { .. } => { + ImplAssocItemValue::DefaultedFn {} + } + ty::AssocKind::Const { .. } => { + ImplAssocItemValue::DefaultedConst {} + } + } + } + }; + + ImplAssocItem { + name: decl_assoc.opt_name().sinto(s), + value, + required_impl_exprs, + decl_def, + } + }) + .collect(); + assert!(item_map.is_empty()); + FullDefKind::TraitImpl { + param_env, + trait_pred, + implied_impl_exprs: required_impl_exprs, + items, + } + } + } + } + RDefKind::Fn { .. } => FullDefKind::Fn { + param_env: get_param_env(s, def_id), + inline: tcx.codegen_fn_attrs(def_id).inline.sinto(s), + is_const: tcx.constness(def_id) == rustc_hir::Constness::Const, + sig: tcx.fn_sig(def_id).instantiate_identity().sinto(s), + body: Body::body(def_id, s), + }, + RDefKind::AssocFn { .. } => FullDefKind::AssocFn { + parent: tcx.parent(def_id).sinto(s), + param_env: get_param_env(s, def_id), + associated_item: tcx.associated_item(def_id).sinto(s), + inline: tcx.codegen_fn_attrs(def_id).inline.sinto(s), + is_const: tcx.constness(def_id) == rustc_hir::Constness::Const, + sig: get_method_sig(s).sinto(s), + body: Body::body(def_id, s), + }, + RDefKind::Closure { .. } => { + let closure_ty = tcx.type_of(def_id).instantiate_identity(); + let ty::TyKind::Closure(_, args) = closure_ty.kind() else { + unreachable!() + }; + FullDefKind::Closure { + parent: tcx.parent(def_id).sinto(s), + is_const: tcx.constness(def_id) == rustc_hir::Constness::Const, + args: ClosureArgs::sfrom(s, def_id, args.as_closure()), + once_shim: closure_once_shim(tcx, closure_ty) + .and_then(|body| Body::from_mir(s, body)), + drop_glue: drop_glue_shim(tcx, def_id).and_then(|body| Body::from_mir(s, body)), + } + } + RDefKind::Const { .. } => FullDefKind::Const { + param_env: get_param_env(s, def_id), + ty: tcx.type_of(def_id).instantiate_identity().sinto(s), + body: Body::body(def_id, s), + }, + RDefKind::AssocConst { .. } => FullDefKind::AssocConst { + parent: tcx.parent(def_id).sinto(s), + param_env: get_param_env(s, def_id), + associated_item: tcx.associated_item(def_id).sinto(s), + ty: tcx.type_of(def_id).instantiate_identity().sinto(s), + body: Body::body(def_id, s), + }, + RDefKind::AnonConst { .. } => FullDefKind::AnonConst { + param_env: get_param_env(s, def_id), + ty: tcx.type_of(def_id).instantiate_identity().sinto(s), + body: Body::body(def_id, s), + }, + RDefKind::InlineConst { .. } => FullDefKind::InlineConst { + param_env: get_param_env(s, def_id), + ty: tcx.type_of(def_id).instantiate_identity().sinto(s), + body: Body::body(def_id, s), + }, + RDefKind::Static { + safety, + mutability, + nested, + .. + } => FullDefKind::Static { + param_env: get_param_env(s, def_id), + safety: safety.sinto(s), + mutability: mutability.sinto(s), + nested: nested.sinto(s), + ty: tcx.type_of(def_id).instantiate_identity().sinto(s), + body: Body::body(def_id, s), + }, + RDefKind::ExternCrate => FullDefKind::ExternCrate, + RDefKind::Use => FullDefKind::Use, + RDefKind::Mod { .. } => FullDefKind::Mod { + items: get_mod_children(tcx, def_id).sinto(s), + }, + RDefKind::ForeignMod { .. } => FullDefKind::ForeignMod { + items: get_foreign_mod_children(tcx, def_id).sinto(s), + }, + RDefKind::TyParam => FullDefKind::TyParam, + RDefKind::ConstParam => FullDefKind::ConstParam, + RDefKind::LifetimeParam => FullDefKind::LifetimeParam, + RDefKind::Variant => FullDefKind::Variant, + RDefKind::Ctor(ctor_of, _) => get_ctor_contents(s, ctor_of.sinto(s)), + RDefKind::Field => FullDefKind::Field, + RDefKind::Macro(kind) => FullDefKind::Macro(kind.sinto(s)), + RDefKind::GlobalAsm => FullDefKind::GlobalAsm, + RDefKind::SyntheticCoroutineBody => FullDefKind::SyntheticCoroutineBody, + } +} + /// An associated item in a trait impl. This can be an item provided by the trait impl, or an item /// that reuses the trait decl default value. #[derive_group(Serializers)] @@ -752,122 +936,6 @@ fn get_self_predicate<'tcx, S: UnderOwnerState<'tcx>>(s: &S) -> TraitPredicate { pred.sinto(s) } -#[cfg(feature = "rustc")] -fn get_impl_contents<'tcx, S, Body>(s: &S) -> FullDefKind -where - S: UnderOwnerState<'tcx>, - Body: IsBody + TypeMappable, -{ - use std::collections::HashMap; - let tcx = s.base().tcx; - let impl_def_id = s.owner_id(); - let param_env = get_param_env(s, impl_def_id); - match tcx.impl_subject(impl_def_id).instantiate_identity() { - ty::ImplSubject::Inherent(ty) => { - let items = tcx - .associated_items(impl_def_id) - .in_definition_order() - .map(|assoc| { - let def_id = assoc.def_id.sinto(s); - (assoc.sinto(s), def_id.full_def(s)) - }) - .collect::>(); - FullDefKind::InherentImpl { - param_env, - ty: ty.sinto(s), - items, - } - } - ty::ImplSubject::Trait(trait_ref) => { - // Also record the polarity. - let polarity = tcx.impl_polarity(impl_def_id); - let trait_pred = TraitPredicate { - trait_ref: trait_ref.sinto(s), - is_positive: matches!(polarity, ty::ImplPolarity::Positive), - }; - // Impl exprs required by the trait. - let required_impl_exprs = - solve_item_implied_traits(s, trait_ref.def_id, trait_ref.args); - - let mut item_map: HashMap = tcx - .associated_items(impl_def_id) - .in_definition_order() - .map(|assoc| (assoc.trait_item_def_id.unwrap(), assoc)) - .collect(); - let items = tcx - .associated_items(trait_ref.def_id) - .in_definition_order() - .map(|decl_assoc| { - let decl_def_id = decl_assoc.def_id; - let decl_def = decl_def_id.sinto(s).full_def(s); - // Impl exprs required by the item. - let required_impl_exprs; - let value = match item_map.remove(&decl_def_id) { - Some(impl_assoc) => { - required_impl_exprs = { - let item_args = - ty::GenericArgs::identity_for_item(tcx, impl_assoc.def_id); - // Subtlety: we have to add the GAT arguments (if any) to the trait ref arguments. - let args = item_args.rebase_onto(tcx, impl_def_id, trait_ref.args); - let state_with_id = - with_owner_id(s.base(), (), (), impl_assoc.def_id); - solve_item_implied_traits(&state_with_id, decl_def_id, args) - }; - - ImplAssocItemValue::Provided { - def: impl_assoc.def_id.sinto(s).full_def(s), - is_override: decl_assoc.defaultness(tcx).has_value(), - } - } - None => { - required_impl_exprs = if tcx.generics_of(decl_def_id).is_own_empty() { - // Non-GAT case. - let item_args = - ty::GenericArgs::identity_for_item(tcx, decl_def_id); - let args = item_args.rebase_onto(tcx, impl_def_id, trait_ref.args); - let state_with_id = with_owner_id(s.base(), (), (), impl_def_id); - solve_item_implied_traits(&state_with_id, decl_def_id, args) - } else { - // FIXME: For GATs, we need a param_env that has the arguments of - // the impl plus those of the associated type, but there's no - // def_id with that param_env. - vec![] - }; - match decl_assoc.kind { - ty::AssocKind::Type { .. } => { - let ty = tcx - .type_of(decl_def_id) - .instantiate(tcx, trait_ref.args) - .sinto(s); - ImplAssocItemValue::DefaultedTy { ty } - } - ty::AssocKind::Fn { .. } => ImplAssocItemValue::DefaultedFn {}, - ty::AssocKind::Const { .. } => { - ImplAssocItemValue::DefaultedConst {} - } - } - } - }; - - ImplAssocItem { - name: decl_assoc.opt_name().sinto(s), - value, - required_impl_exprs, - decl_def, - } - }) - .collect(); - assert!(item_map.is_empty()); - FullDefKind::TraitImpl { - param_env, - trait_pred, - implied_impl_exprs: required_impl_exprs, - items, - } - } - } -} - /// The signature of a method impl may be a subtype of the one expected from the trait decl, as in /// the example below. For correctness, we must be able to map from the method generics declared in /// the trait to the actual method generics. Because this would require type inference, we instead From 6ed20390f86bc5fb6cf8a3201736177859dcbf5b Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 7 Jul 2025 14:02:08 +0200 Subject: [PATCH 08/51] Don't add drop bounds for closure fake type params --- frontend/exporter/src/traits/utils.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/exporter/src/traits/utils.rs b/frontend/exporter/src/traits/utils.rs index cf0d94162..0eb639ff5 100644 --- a/frontend/exporter/src/traits/utils.rs +++ b/frontend/exporter/src/traits/utils.rs @@ -92,9 +92,11 @@ pub fn required_predicates<'tcx>( let self_clause = self_predicate(tcx, trait_def_id).upcast(tcx); predicates.to_mut().insert(0, (self_clause, DUMMY_SP)); } - if add_drop { + if add_drop && !matches!(def_kind, Closure) { // Add a `T: Drop` bound for every generic, unless the current trait is `Drop` itself, or a // built-in marker trait that we know doesn't need the bound. + // We skip closures because they have fictitious weird type parameters in their `own_args`, + // that we don't want to add `Drop` bounds for. let lang_item = tcx.as_lang_item(def_id); if !matches!( lang_item, From 904ed6312a8bfbea3e6aeec465447dfc3acf7b2b Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 7 Jul 2025 14:14:55 +0200 Subject: [PATCH 09/51] Make `Drop` bounds on traits be implied instead of required --- frontend/exporter/src/traits/utils.rs | 81 +++++++++++++++++---------- 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/frontend/exporter/src/traits/utils.rs b/frontend/exporter/src/traits/utils.rs index 0eb639ff5..d701381be 100644 --- a/frontend/exporter/src/traits/utils.rs +++ b/frontend/exporter/src/traits/utils.rs @@ -50,6 +50,32 @@ pub fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> Predicates<'_> { result } +/// Add `T: Drop` bounds for every generic parameter of the given item. +fn add_drop_bounds<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + predicates: &mut Vec<(Clause<'tcx>, Span)>, +) { + let def_kind = tcx.def_kind(def_id); + if matches!(def_kind, DefKind::Closure) { + // Closures have fictitious weird type parameters in their `own_args` that we don't want to + // add `Drop` bounds for. + return; + } + // Add a `T: Drop` bound for every generic. + let drop_trait = tcx.lang_items().drop_trait().unwrap(); + let extra_bounds = tcx + .generics_of(def_id) + .own_params + .iter() + .filter(|param| matches!(param.kind, GenericParamDefKind::Type { .. })) + .map(|param| tcx.mk_param_from_def(param)) + .map(|ty| Binder::dummy(TraitRef::new(tcx, drop_trait, [ty]))) + .map(|tref| tref.upcast(tcx)) + .map(|clause| (clause, DUMMY_SP)); + predicates.extend(extra_bounds); +} + /// The predicates that must hold to mention this item. E.g. /// /// ```ignore @@ -92,35 +118,10 @@ pub fn required_predicates<'tcx>( let self_clause = self_predicate(tcx, trait_def_id).upcast(tcx); predicates.to_mut().insert(0, (self_clause, DUMMY_SP)); } - if add_drop && !matches!(def_kind, Closure) { - // Add a `T: Drop` bound for every generic, unless the current trait is `Drop` itself, or a - // built-in marker trait that we know doesn't need the bound. - // We skip closures because they have fictitious weird type parameters in their `own_args`, - // that we don't want to add `Drop` bounds for. - let lang_item = tcx.as_lang_item(def_id); - if !matches!( - lang_item, - Some( - LangItem::Drop - | LangItem::Sized - | LangItem::MetaSized - | LangItem::PointeeSized - | LangItem::DiscriminantKind - | LangItem::PointeeTrait - ) - ) { - let drop_trait = tcx.lang_items().drop_trait().unwrap(); - let extra_bounds = tcx - .generics_of(def_id) - .own_params - .iter() - .filter(|param| matches!(param.kind, GenericParamDefKind::Type { .. })) - .map(|param| tcx.mk_param_from_def(param)) - .map(|ty| Binder::dummy(TraitRef::new(tcx, drop_trait, [ty]))) - .map(|tref| tref.upcast(tcx)) - .map(|clause| (clause, DUMMY_SP)); - predicates.to_mut().extend(extra_bounds); - } + if add_drop && !matches!(def_kind, Trait | TraitAlias) { + // Add a `T: Drop` bound for every generic. For traits we consider these predicates implied + // instead of required. + add_drop_bounds(tcx, def_id, predicates.to_mut()); } predicates } @@ -153,7 +154,27 @@ pub fn implied_predicates<'tcx>( let parent = tcx.opt_parent(def_id); match tcx.def_kind(def_id) { // We consider all predicates on traits to be outputs - Trait | TraitAlias => predicates_defined_on(tcx, def_id), + Trait | TraitAlias => { + let mut predicates = predicates_defined_on(tcx, def_id); + if add_drop { + // Add a `T: Drop` bound for every generic, unless the current trait is `Drop` itself, or a + // built-in marker trait that we know doesn't need the bound. + if !matches!( + tcx.as_lang_item(def_id), + Some( + LangItem::Drop + | LangItem::Sized + | LangItem::MetaSized + | LangItem::PointeeSized + | LangItem::DiscriminantKind + | LangItem::PointeeTrait + ) + ) { + add_drop_bounds(tcx, def_id, predicates.to_mut()); + } + } + predicates + } AssocTy if matches!(tcx.def_kind(parent.unwrap()), Trait) => { // `skip_binder` is for the GAT `EarlyBinder` let mut predicates = Cow::Borrowed(tcx.explicit_item_bounds(def_id).skip_binder()); From 55ef02fa08eea8dc1d3b0b9105c04f97f24a4ac4 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 7 Jul 2025 15:14:48 +0200 Subject: [PATCH 10/51] Don't add `Drop` bounds to the `Tuple` marker trait --- frontend/exporter/src/traits/utils.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/exporter/src/traits/utils.rs b/frontend/exporter/src/traits/utils.rs index d701381be..242c33676 100644 --- a/frontend/exporter/src/traits/utils.rs +++ b/frontend/exporter/src/traits/utils.rs @@ -168,6 +168,7 @@ pub fn implied_predicates<'tcx>( | LangItem::PointeeSized | LangItem::DiscriminantKind | LangItem::PointeeTrait + | LangItem::Tuple ) ) { add_drop_bounds(tcx, def_id, predicates.to_mut()); From 9981e4ed2fe01df53b261a4b82bd2262e1b97f08 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 7 Jul 2025 15:17:21 +0200 Subject: [PATCH 11/51] Provide resolved `ImplExpr`s for virtual trait impls --- frontend/exporter/src/types/new/full_def.rs | 78 +++++++++++++++++++-- 1 file changed, 71 insertions(+), 7 deletions(-) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 9d41f8ddf..952a80bbb 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -278,12 +278,14 @@ pub enum FullDefKind { /// Note: the (early-bound) generics of a closure are the same as those of the item in which it /// is defined. Closure { - /// The enclosing item. Note: this item could itself be a closure; to get the generics, you - /// might have to recurse through several layers of parents until you find a function or - /// constant. - parent: DefId, - is_const: bool, args: ClosureArgs, + is_const: bool, + /// Info required to construct a virtual `FnOnce` impl for this closure. + fn_once_impl: Box, + /// Info required to construct a virtual `FnMut` impl for this closure. + fn_mut_impl: Option>, + /// Info required to construct a virtual `Fn` impl for this closure. + fn_impl: Option>, /// For `FnMut`&`Fn` closures: the MIR for the `call_once` method; it simply calls /// `call_mut`. once_shim: Option, @@ -598,17 +600,32 @@ where body: Body::body(def_id, s), }, RDefKind::Closure { .. } => { + use ty::ClosureKind::{Fn, FnMut}; let closure_ty = tcx.type_of(def_id).instantiate_identity(); let ty::TyKind::Closure(_, args) = closure_ty.kind() else { unreachable!() }; + let closure = args.as_closure(); + // We lose lifetime information here. Eventually would be nice not to. + let input_ty = erase_free_regions(tcx, closure.sig().input(0).skip_binder()); + let trait_args = [closure_ty, input_ty]; + let fn_once_trait = tcx.lang_items().fn_once_trait().unwrap(); + let fn_mut_trait = tcx.lang_items().fn_mut_trait().unwrap(); + let fn_trait = tcx.lang_items().fn_trait().unwrap(); FullDefKind::Closure { - parent: tcx.parent(def_id).sinto(s), is_const: tcx.constness(def_id) == rustc_hir::Constness::Const, - args: ClosureArgs::sfrom(s, def_id, args.as_closure()), + args: ClosureArgs::sfrom(s, def_id, closure), once_shim: closure_once_shim(tcx, closure_ty) .and_then(|body| Body::from_mir(s, body)), drop_glue: drop_glue_shim(tcx, def_id).and_then(|body| Body::from_mir(s, body)), + fn_once_impl: virtual_impl_for( + s, + ty::TraitRef::new(tcx, fn_once_trait, trait_args), + ), + fn_mut_impl: matches!(closure.kind(), FnMut | Fn) + .then(|| virtual_impl_for(s, ty::TraitRef::new(tcx, fn_mut_trait, trait_args))), + fn_impl: matches!(closure.kind(), Fn) + .then(|| virtual_impl_for(s, ty::TraitRef::new(tcx, fn_trait, trait_args))), } } RDefKind::Const { .. } => FullDefKind::Const { @@ -716,6 +733,19 @@ pub enum ImplAssocItemValue { DefaultedConst, } +/// Partial data for a trait impl, used for fake trait impls that we generate ourselves such as +/// `FnOnce` and `Drop` impls. +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] +pub struct VirtualTraitImpl { + /// The trait that is implemented by this impl block. + pub trait_pred: TraitPredicate, + /// The `ImplExpr`s required to satisfy the predicates on the trait declaration. + pub implied_impl_exprs: Vec, + /// Tye associated types and their predicates, in definition order. + pub types: Vec<(Ty, Vec)>, +} + impl FullDef { pub fn def_id(&self) -> &DefId { &self.def_id @@ -936,6 +966,40 @@ fn get_self_predicate<'tcx, S: UnderOwnerState<'tcx>>(s: &S) -> TraitPredicate { pred.sinto(s) } +/// Do the trait resolution necessary to create a new impl for the given trait_ref. Used when we +/// generate fake trait impls e.g. for `FnOnce` and `Drop`. +#[cfg(feature = "rustc")] +fn virtual_impl_for<'tcx, S>(s: &S, trait_ref: ty::TraitRef<'tcx>) -> Box +where + S: UnderOwnerState<'tcx>, +{ + let tcx = s.base().tcx; + let trait_pred = TraitPredicate { + trait_ref: trait_ref.sinto(s), + is_positive: true, + }; + // Impl exprs required by the trait. + let required_impl_exprs = solve_item_implied_traits(s, trait_ref.def_id, trait_ref.args); + let types = tcx + .associated_items(trait_ref.def_id) + .in_definition_order() + .filter(|assoc| matches!(assoc.kind, ty::AssocKind::Type { .. })) + .map(|assoc| { + // This assumes non-GAT because this is for builtin-trait (that don't + // have GATs). + let ty = ty::Ty::new_projection(tcx, assoc.def_id, trait_ref.args).sinto(s); + // Impl exprs required by the type. + let required_impl_exprs = solve_item_implied_traits(s, assoc.def_id, trait_ref.args); + (ty, required_impl_exprs) + }) + .collect(); + Box::new(VirtualTraitImpl { + trait_pred, + implied_impl_exprs: required_impl_exprs, + types, + }) +} + /// The signature of a method impl may be a subtype of the one expected from the trait decl, as in /// the example below. For correctness, we must be able to map from the method generics declared in /// the trait to the actual method generics. Because this would require type inference, we instead From b955547dafd2998cd01152dafc82b9d6aa9a91d2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 9 Jul 2025 11:28:24 +0200 Subject: [PATCH 12/51] Update rustc again --- engine/lib/import_thir.ml | 2 -- flake.lock | 6 +++--- frontend/exporter/Cargo.toml | 2 +- frontend/exporter/src/lib.rs | 1 - frontend/exporter/src/types/def_id.rs | 9 ++++++++ frontend/exporter/src/types/hir.rs | 4 ++-- frontend/exporter/src/types/ty.rs | 21 +++++++++++-------- rust-toolchain.toml | 2 +- .../toolchain__traits into-fstar.snap | 12 +++++++---- 9 files changed, 36 insertions(+), 23 deletions(-) diff --git a/engine/lib/import_thir.ml b/engine/lib/import_thir.ml index eecd488eb..44292f0dc 100644 --- a/engine/lib/import_thir.ml +++ b/engine/lib/import_thir.ml @@ -1101,8 +1101,6 @@ end) : EXPR = struct match non_traits with | [] -> TDyn { witness = W.dyn; goals } | _ -> assertion_failure [ span ] "type Dyn with non trait predicate") - | Dynamic (_, _, DynStar) -> - unimplemented ~issue_id:931 [ span ] "type DynStar" | Coroutine _ -> unimplemented ~issue_id:924 [ span ] "Got type `Coroutine`: coroutines are not supported by hax" diff --git a/flake.lock b/flake.lock index c263241e4..90ae266ac 100644 --- a/flake.lock +++ b/flake.lock @@ -127,11 +127,11 @@ ] }, "locked": { - "lastModified": 1751338093, - "narHash": "sha256-/yd9nPcTfUZPFtwjRbdB5yGLdt3LTPqz6Ja63Joiahs=", + "lastModified": 1752028888, + "narHash": "sha256-LRj3/PUpII6taWOrX1w/OeI6f1ncND02PP/kEHvPCqU=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "6cfb7821732dac2d3e2dea857a5613d3b856c20c", + "rev": "a0f1c656e053463b47639234b151a05e4441bb19", "type": "github" }, "original": { diff --git a/frontend/exporter/Cargo.toml b/frontend/exporter/Cargo.toml index 35ed4c09a..f19eb4381 100644 --- a/frontend/exporter/Cargo.toml +++ b/frontend/exporter/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "hax-frontend-exporter" +edition = "2024" version.workspace = true authors.workspace = true license.workspace = true homepage.workspace = true -edition.workspace = true repository.workspace = true readme.workspace = true description = "Provides mirrors of the algebraic data types used in the Rust compilers, removing indirections and inlining various pieces of information." diff --git a/frontend/exporter/src/lib.rs b/frontend/exporter/src/lib.rs index a4c851910..ef6af0388 100644 --- a/frontend/exporter/src/lib.rs +++ b/frontend/exporter/src/lib.rs @@ -1,6 +1,5 @@ #![allow(rustdoc::private_intra_doc_links)] #![cfg_attr(feature = "rustc", feature(if_let_guard))] -#![cfg_attr(feature = "rustc", feature(let_chains))] #![cfg_attr(feature = "rustc", feature(macro_metavar_expr))] #![cfg_attr(feature = "rustc", feature(rustc_private))] #![cfg_attr(feature = "rustc", feature(sized_hierarchy))] diff --git a/frontend/exporter/src/types/def_id.rs b/frontend/exporter/src/types/def_id.rs index c0a10edc5..14196789c 100644 --- a/frontend/exporter/src/types/def_id.rs +++ b/frontend/exporter/src/types/def_id.rs @@ -21,6 +21,8 @@ use crate::{AdtInto, JsonSchema}; use {rustc_hir as hir, rustc_hir::def_id::DefId as RDefId, rustc_middle::ty}; pub type Symbol = String; +#[cfg(not(feature = "extract_names_mode"))] +pub type ByteSymbol = Vec; #[cfg(all(not(feature = "extract_names_mode"), feature = "rustc"))] impl<'t, S> SInto for rustc_span::symbol::Symbol { @@ -29,6 +31,13 @@ impl<'t, S> SInto for rustc_span::symbol::Symbol { } } +#[cfg(all(not(feature = "extract_names_mode"), feature = "rustc"))] +impl<'t, S> SInto for rustc_span::symbol::ByteSymbol { + fn sinto(&self, _s: &S) -> ByteSymbol { + self.as_byte_str().to_owned() + } +} + /// Reflects [`hir::Safety`] #[cfg_attr(not(feature = "extract_names_mode"), derive(AdtInto, JsonSchema))] #[cfg_attr(not(feature = "extract_names_mode"), args(, from: hir::Safety, state: S as _s))] diff --git a/frontend/exporter/src/types/hir.rs b/frontend/exporter/src/types/hir.rs index 669063f26..b7431771f 100644 --- a/frontend/exporter/src/types/hir.rs +++ b/frontend/exporter/src/types/hir.rs @@ -1050,8 +1050,8 @@ pub enum StrStyle { #[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum LitKind { Str(Symbol, StrStyle), - ByteStr(Vec, StrStyle), - CStr(Vec, StrStyle), + ByteStr(ByteSymbol, StrStyle), + CStr(ByteSymbol, StrStyle), Byte(u8), Char(char), Int( diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index bfc1fe3e9..cf03aaa05 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -94,22 +94,22 @@ pub struct ExistentialProjection { #[args(, from: ty::DynKind, state: S as _s)] pub enum DynKind { Dyn, - DynStar, } /// Reflects [`ty::BoundTyKind`] #[derive_group(Serializers)] #[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::BoundTyKind, state: S as gstate)] +#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::BoundTyKind, state: S as s)] pub enum BoundTyKind { Anon, + #[custom_arm(&FROM_TYPE::Param(def_id) => TO_TYPE::Param(def_id.sinto(s), s.base().tcx.item_name(def_id).sinto(s)),)] Param(DefId, Symbol), } /// Reflects [`ty::BoundTy`] #[derive_group(Serializers)] #[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::BoundTy, state: S as gstate)] +#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::BoundTy, state: S as s)] pub struct BoundTy { pub var: BoundVar, pub kind: BoundTyKind, @@ -120,9 +120,11 @@ sinto_as_usize!(rustc_middle::ty, BoundVar); /// Reflects [`ty::BoundRegionKind`] #[derive_group(Serializers)] #[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::BoundRegionKind, state: S as gstate)] +#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::BoundRegionKind, state: S as s)] pub enum BoundRegionKind { Anon, + NamedAnon(Symbol), + #[custom_arm(&FROM_TYPE::Named(def_id) => TO_TYPE::Named(def_id.sinto(s), s.base().tcx.item_name(def_id).sinto(s)),)] Named(DefId, Symbol), ClosureEnv, } @@ -130,7 +132,7 @@ pub enum BoundRegionKind { /// Reflects [`ty::BoundRegion`] #[derive_group(Serializers)] #[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::BoundRegion, state: S as gstate)] +#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::BoundRegion, state: S as s)] pub struct BoundRegion { pub var: BoundVar, pub kind: BoundRegionKind, @@ -370,7 +372,7 @@ impl VariantDef { /// Reflects [`ty::EarlyParamRegion`] #[derive_group(Serializers)] #[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::EarlyParamRegion, state: S as gstate)] +#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::EarlyParamRegion, state: S as s)] pub struct EarlyParamRegion { pub index: u32, pub name: Symbol, @@ -379,7 +381,7 @@ pub struct EarlyParamRegion { /// Reflects [`ty::LateParamRegion`] #[derive_group(Serializers)] #[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::LateParamRegion, state: S as gstate)] +#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::LateParamRegion, state: S as s)] pub struct LateParamRegion { pub scope: DefId, pub kind: LateParamRegionKind, @@ -388,9 +390,11 @@ pub struct LateParamRegion { /// Reflects [`ty::LateParamRegionKind`] #[derive_group(Serializers)] #[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::LateParamRegionKind, state: S as gstate)] +#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::LateParamRegionKind, state: S as s)] pub enum LateParamRegionKind { Anon(u32), + NamedAnon(u32, Symbol), + #[custom_arm(&FROM_TYPE::Named(def_id) => TO_TYPE::Named(def_id.sinto(s), s.base().tcx.item_name(def_id).sinto(s)),)] Named(DefId, Symbol), ClosureEnv, } @@ -1088,7 +1092,6 @@ pub enum PointerCoercion { ClosureFnPointer(Safety), MutToConstPointer, ArrayToPointer, - DynStar, Unsize, } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 3a87a82e7..1f96d2c9e 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-06-30" +channel = "nightly-2025-07-08" components = [ "rustc-dev", "llvm-tools-preview" , "rust-analysis" , "rust-src" , "rustfmt" ] diff --git a/test-harness/src/snapshots/toolchain__traits into-fstar.snap b/test-harness/src/snapshots/toolchain__traits into-fstar.snap index f0132d6a7..3bac0d098 100644 --- a/test-harness/src/snapshots/toolchain__traits into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__traits into-fstar.snap @@ -666,11 +666,15 @@ let iter_option (#v_T: Type0) (x: Core.Option.t_Option v_T) : Core.Option.t_Into (Core.Option.impl__as_ref #v_T x <: Core.Option.t_Option v_T) let uuse_iimpl_trait (_: Prims.unit) : Prims.unit = - let iter:_ = iter_option #bool (Core.Option.Option_Some false <: Core.Option.t_Option bool) in - let tmp0, out:(_ & Core.Option.t_Option bool) = - Core.Iter.Traits.Iterator.f_next #_ #FStar.Tactics.Typeclasses.solve iter + let iter:Core.Option.t_IntoIter bool = + iter_option #bool (Core.Option.Option_Some false <: Core.Option.t_Option bool) in - let iter:_ = tmp0 in + let tmp0, out:(Core.Option.t_IntoIter bool & Core.Option.t_Option bool) = + Core.Iter.Traits.Iterator.f_next #(Core.Option.t_IntoIter bool) + #FStar.Tactics.Typeclasses.solve + iter + in + let iter:Core.Option.t_IntoIter bool = tmp0 in let _:Core.Option.t_Option bool = out in () From c73c4807c026fb1380ff26a1b3ea6b738ddb4db8 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 9 Jul 2025 19:16:31 +0200 Subject: [PATCH 13/51] Add variance information to generic parameters --- frontend/exporter/src/types/ty.rs | 37 +++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index cf03aaa05..0a12b5348 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -713,6 +713,18 @@ impl> SInto> for ty::List { } } +/// Reflects [`ty::Variance`] +#[derive(AdtInto)] +#[args(, from: ty::Variance, state: S as _s)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] +pub enum Variance { + Covariant, + Invariant, + Contravariant, + Bivariant, +} + /// Reflects [`ty::GenericParamDef`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::GenericParamDef, state: S as s)] @@ -734,6 +746,19 @@ pub struct GenericParamDef { } )] pub kind: GenericParamDefKind, + /// Variance of this type parameter, if sensible. + #[value({ + use rustc_hir::def::DefKind::*; + let tcx = s.base().tcx; + let parent = tcx.parent(self.def_id); + match tcx.def_kind(parent) { + Fn | AssocFn | Enum | Struct | Union | Ctor(..) | OpaqueTy => { + Some(tcx.variances_of(parent)[self.index as usize].sinto(s)) + } + _ => None + } + })] + pub variance: Option, } /// Reflects [`ty::GenericParamDefKind`] @@ -982,18 +1007,6 @@ pub enum TyKind { Todo(String), } -/// Reflects [`ty::Variance`] -#[derive(AdtInto)] -#[args(, from: ty::Variance, state: S as _s)] -#[derive_group(Serializers)] -#[derive(Clone, Debug, JsonSchema)] -pub enum Variance { - Covariant, - Invariant, - Contravariant, - Bivariant, -} - /// Reflects [`ty::CanonicalUserTypeAnnotation`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::CanonicalUserTypeAnnotation<'tcx>, state: S as gstate)] From e2d69df5273af7570951de226b1f10e7aa880aec Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 8 Jul 2025 14:39:38 +0200 Subject: [PATCH 14/51] Cleanup the creation of `State` structs --- frontend/exporter/src/body.rs | 21 ++--- frontend/exporter/src/state.rs | 98 ++++++++------------- frontend/exporter/src/traits.rs | 4 +- frontend/exporter/src/types/def_id.rs | 4 +- frontend/exporter/src/types/hir.rs | 24 ++--- frontend/exporter/src/types/mir.rs | 4 +- frontend/exporter/src/types/new/full_def.rs | 19 ++-- frontend/exporter/src/types/thir.rs | 6 +- frontend/exporter/src/types/ty.rs | 10 +-- 9 files changed, 77 insertions(+), 113 deletions(-) diff --git a/frontend/exporter/src/body.rs b/frontend/exporter/src/body.rs index 436a42f98..57bba80d6 100644 --- a/frontend/exporter/src/body.rs +++ b/frontend/exporter/src/body.rs @@ -97,7 +97,7 @@ mod module { } pub use store::*; - pub fn get_thir<'tcx, S: UnderOwnerState<'tcx>>( + pub fn get_thir<'tcx, S: BaseState<'tcx>>( did: RLocalDefId, s: &S, ) -> ( @@ -133,7 +133,7 @@ mod module { } } - pub fn make_fn_def<'tcx, Body: IsBody, S: UnderOwnerState<'tcx>>( + pub fn make_fn_def<'tcx, Body: IsBody, S: BaseState<'tcx>>( fn_sig: &rustc_hir::FnSig, body_id: &rustc_hir::BodyId, s: &S, @@ -142,7 +142,7 @@ mod module { let ldid = hir_id.owner.def_id; let (thir, expr_entrypoint) = get_thir(ldid, s); - let s = &with_owner_id(s.base(), thir.clone(), (), ldid.to_def_id()); + let s = &s.with_owner_id(ldid.to_def_id()).with_thir(thir.clone()); FnDef { params: thir.params.raw.sinto(s), ret: thir.exprs[expr_entrypoint].ty.sinto(s), @@ -178,9 +178,10 @@ mod module { } } impl IsBody for ThirBody { - fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RDefId, s: &S) -> Option { + fn body<'tcx, S: BaseState<'tcx>>(did: RDefId, s: &S) -> Option { let did = did.as_local()?; let (thir, expr) = get_thir(did, s); + let s = &s.with_owner_id(did.to_def_id()); Some(if *CORE_EXTRACTION_MODE { let expr = &thir.exprs[expr]; Decorated { @@ -191,7 +192,7 @@ mod module { span: expr.span.sinto(s), } } else { - expr.sinto(&with_owner_id(s.base(), thir, (), did.to_def_id())) + expr.sinto(&s.with_thir(thir)) }) } } @@ -206,7 +207,7 @@ mod module { fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RDefId, s: &S) -> Option { MirKind::get_mir(s.base().tcx, did, |body| { let body = Rc::new(body.clone()); - body.sinto(&with_owner_id(s.base(), (), body.clone(), did)) + body.sinto(&s.with_mir(body.clone())) }) } fn from_mir<'tcx, S: UnderOwnerState<'tcx>>( @@ -214,13 +215,7 @@ mod module { body: rustc_middle::mir::Body<'tcx>, ) -> Option { let body = Rc::new(body.clone()); - let s = &State { - base: s.base(), - owner_id: s.owner_id(), - mir: body.clone(), - binder: (), - thir: (), - }; + let s = &s.with_mir(body.clone()); Some(body.sinto(s)) } } diff --git a/frontend/exporter/src/state.rs b/frontend/exporter/src/state.rs index bf621c216..7a907d5fe 100644 --- a/frontend/exporter/src/state.rs +++ b/frontend/exporter/src/state.rs @@ -236,82 +236,62 @@ impl<'tcx> StateWithBase<'tcx> { } } -impl<'tcx> StateWithOwner<'tcx> { - pub fn new_from_state_and_id>(s: &S, id: rustc_hir::def_id::DefId) -> Self { +pub trait BaseState<'tcx>: IsState<'tcx> + HasBase<'tcx> + Clone { + /// Updates the OnwerId in a state, making sure to override `opt_def_id` in base as well. + fn with_owner_id(&self, owner_id: rustc_hir::def_id::DefId) -> StateWithOwner<'tcx> { + let mut base = self.base(); + base.opt_def_id = Some(owner_id); State { + owner_id, + base, thir: (), mir: (), - owner_id: id, binder: (), - base: s.base().clone(), } } } -impl<'tcx> StateWithMir<'tcx> { - pub fn new_from_mir( - tcx: rustc_middle::ty::TyCtxt<'tcx>, - options: hax_frontend_exporter_options::Options, - mir: rustc_middle::mir::Body<'tcx>, - owner_id: rustc_hir::def_id::DefId, - ) -> Self { - Self { +impl<'tcx, T: IsState<'tcx> + HasBase<'tcx> + Clone> BaseState<'tcx> for T {} + +/// State of anything below an `owner`. +pub trait UnderOwnerState<'tcx>: BaseState<'tcx> + HasOwnerId { + fn with_base(&self, base: types::Base<'tcx>) -> StateWithOwner<'tcx> { + State { + owner_id: self.owner_id(), + base, thir: (), - mir: Rc::new(mir), - owner_id, + mir: (), binder: (), - base: Base::new(tcx, options), } } -} -impl<'tcx> StateWithThir<'tcx> { - pub fn from_thir( - base: Base<'tcx>, - owner_id: rustc_hir::def_id::DefId, - thir: types::RcThir<'tcx>, - ) -> Self { - Self { + fn with_binder(&self, binder: types::UnitBinder<'tcx>) -> StateWithBinder<'tcx> { + State { + base: self.base(), + owner_id: self.owner_id(), + binder, + thir: (), + mir: (), + } + } + fn with_thir(&self, thir: types::RcThir<'tcx>) -> StateWithThir<'tcx> { + State { + base: self.base(), + owner_id: self.owner_id(), thir, mir: (), - owner_id, binder: (), - base, } } -} - -impl<'tcx> StateWithOwner<'tcx> { - pub fn from_under_owner>(s: &S) -> Self { - Self { - base: s.base(), - owner_id: s.owner_id(), + fn with_mir(&self, mir: types::RcMir<'tcx>) -> StateWithMir<'tcx> { + State { + base: self.base(), + owner_id: self.owner_id(), + mir, thir: (), - mir: (), binder: (), } } } - -/// Updates the OnwerId in a state, making sure to override `opt_def_id` in base as well. -pub fn with_owner_id( - mut base: types::Base<'_>, - thir: THIR, - mir: MIR, - owner_id: rustc_hir::def_id::DefId, -) -> State, THIR, MIR, rustc_hir::def_id::DefId, ()> { - base.opt_def_id = Some(owner_id); - State { - thir, - owner_id, - base, - mir, - binder: (), - } -} - -pub trait BaseState<'tcx> = HasBase<'tcx> + Clone + IsState<'tcx>; - -/// State of anything below a `owner_id`. -pub trait UnderOwnerState<'tcx> = BaseState<'tcx> + HasOwnerId; +impl<'tcx, T: BaseState<'tcx> + HasOwnerId> UnderOwnerState<'tcx> for T {} /// State of anything below a binder. pub trait UnderBinderState<'tcx> = UnderOwnerState<'tcx> + HasBinder<'tcx>; @@ -346,9 +326,9 @@ pub trait WithItemCacheExt<'tcx>: UnderOwnerState<'tcx> { impl<'tcx, S: UnderOwnerState<'tcx>> WithItemCacheExt<'tcx> for S {} impl ImplInfos { - fn from(base: Base<'_>, did: rustc_hir::def_id::DefId) -> Self { - let tcx = base.tcx; - let s = &with_owner_id(base, (), (), did); + fn from<'tcx, S: BaseState<'tcx>>(s: &S, did: rustc_hir::def_id::DefId) -> Self { + let tcx = s.base().tcx; + let s = &s.with_owner_id(did); Self { generics: tcx.generics_of(did).sinto(s), @@ -393,6 +373,6 @@ pub fn impl_def_ids_to_impled_types_and_bounds<'tcx, S: BaseState<'tcx>>( }) ) }) - .map(|did| (did.sinto(s), ImplInfos::from(s.base(), did))) + .map(|did| (did.sinto(s), ImplInfos::from(s, did))) .collect() } diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index 6879130f6..1645b0daf 100644 --- a/frontend/exporter/src/traits.rs +++ b/frontend/exporter/src/traits.rs @@ -200,7 +200,7 @@ pub fn super_clause_to_clause_and_impl_expr<'tcx, S: UnderOwnerState<'tcx>>( 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()); + let s = &s.with_owner_id(impl_trait_ref.def_id()); clause.sinto(s).id }; let new_clause = clause.instantiate_supertrait(tcx, impl_trait_ref); @@ -219,7 +219,7 @@ pub fn super_clause_to_clause_and_impl_expr<'tcx, S: UnderOwnerState<'tcx>>( /// This is the entrypoint of the solving. #[cfg(feature = "rustc")] #[tracing::instrument(level = "trace", skip(s))] -pub fn solve_trait<'tcx, S: BaseState<'tcx> + HasOwnerId>( +pub fn solve_trait<'tcx, S: UnderOwnerState<'tcx>>( s: &S, trait_ref: rustc_middle::ty::PolyTraitRef<'tcx>, ) -> ImplExpr { diff --git a/frontend/exporter/src/types/def_id.rs b/frontend/exporter/src/types/def_id.rs index 14196789c..7bb47e285 100644 --- a/frontend/exporter/src/types/def_id.rs +++ b/frontend/exporter/src/types/def_id.rs @@ -310,7 +310,7 @@ pub(crate) fn translate_def_id<'tcx, S: BaseState<'tcx>>(s: &S, def_id: RDefId) let tcx = s.base().tcx; let path = { // Set the def_id so the `CrateRoot` path item can fetch the crate name. - let state_with_id = with_owner_id(s.base(), (), (), def_id); + let state_with_id = s.with_owner_id(def_id); tcx.def_path(def_id) .data .iter() @@ -367,7 +367,7 @@ impl std::convert::From for Path { pub type GlobalIdent = DefId; #[cfg(all(not(feature = "extract_names_mode"), feature = "rustc"))] -impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_hir::def_id::LocalDefId { +impl<'tcx, S: BaseState<'tcx>> SInto for rustc_hir::def_id::LocalDefId { fn sinto(&self, st: &S) -> DefId { self.to_def_id().sinto(st) } diff --git a/frontend/exporter/src/types/hir.rs b/frontend/exporter/src/types/hir.rs index b7431771f..127c42896 100644 --- a/frontend/exporter/src/types/hir.rs +++ b/frontend/exporter/src/types/hir.rs @@ -225,11 +225,11 @@ pub struct Generics { } #[cfg(feature = "rustc")] -impl<'tcx, S: UnderOwnerState<'tcx>, Body: IsBody> SInto> for hir::ImplItemRef { +impl<'tcx, S: BaseState<'tcx>, Body: IsBody> SInto> for hir::ImplItemRef { fn sinto(&self, s: &S) -> ImplItem { let tcx: rustc_middle::ty::TyCtxt = s.base().tcx; let impl_item = tcx.hir_impl_item(self.id); - let s = with_owner_id(s.base(), (), (), impl_item.owner_id.to_def_id()); + let s = s.with_owner_id(impl_item.owner_id.to_def_id()); impl_item.sinto(&s) } } @@ -257,12 +257,12 @@ pub enum LifetimeParamKind { /// Reflects [`hir::AnonConst`] #[derive_group(Serializers)] #[derive(AdtInto, Clone, Debug, JsonSchema)] -#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: hir::AnonConst, state: S as s)] +#[args(<'tcx, S: BaseState<'tcx>>, from: hir::AnonConst, state: S as s)] pub struct AnonConst { pub hir_id: HirId, pub def_id: GlobalIdent, #[map({ - body_from_id::(*x, &with_owner_id(s.base(), (), (), hir_id.owner.to_def_id())) + body_from_id::(*x, &s.with_owner_id(hir_id.owner.to_def_id())) })] pub body: Body, } @@ -509,7 +509,7 @@ pub struct Variant { pub ident: Ident, pub hir_id: HirId, pub def_id: GlobalIdent, - #[map(x.sinto(&with_owner_id(s.base(), (), (), self.def_id.to_def_id())))] + #[map(x.sinto(&s.with_owner_id(self.def_id.to_def_id())))] pub data: VariantData, pub disr_expr: Option>, #[value({ @@ -650,13 +650,7 @@ pub enum ItemKind { Ident, Generics, #[map({ - let s = &State { - base: Base {ty_alias_mode: true, ..s.base()}, - owner_id: s.owner_id(), - thir: (), - mir: (), - binder: (), - }; + let s = &s.with_base(Base { ty_alias_mode: true, ..s.base() }); x.sinto(s) })] Ty, @@ -741,9 +735,9 @@ impl<'tcx, S: UnderOwnerState<'tcx>, Body: IsBody> SInto> for h } #[cfg(feature = "rustc")] -impl<'a, S: UnderOwnerState<'a>, Body: IsBody> SInto> for hir::TraitItemRef { +impl<'a, S: BaseState<'a>, Body: IsBody> SInto> for hir::TraitItemRef { fn sinto(&self, s: &S) -> TraitItem { - let s = with_owner_id(s.base(), (), (), self.id.owner_id.to_def_id()); + let s = s.with_owner_id(self.id.owner_id.to_def_id()); let tcx: rustc_middle::ty::TyCtxt = s.base().tcx; tcx.hir_trait_item(self.id).sinto(&s) } @@ -928,7 +922,7 @@ impl<'tcx, S: BaseState<'tcx>, Body: IsBody> SInto> for hir::Item< | TraitAlias(i, ..) => i.name.to_ident_string(), Use(..) | ForeignMod { .. } | GlobalAsm { .. } | Impl { .. } => String::new(), }; - let s = &with_owner_id(s.base(), (), (), self.owner_id.to_def_id()); + let s = &s.with_owner_id(self.owner_id.to_def_id()); let owner_id: DefId = self.owner_id.sinto(s); let def_id = Path::from(owner_id.clone()) .ends_with(&[name]) diff --git a/frontend/exporter/src/types/mir.rs b/frontend/exporter/src/types/mir.rs index 456f94601..2af9504e7 100644 --- a/frontend/exporter/src/types/mir.rs +++ b/frontend/exporter/src/types/mir.rs @@ -352,7 +352,7 @@ pub struct Terminator { } #[cfg(feature = "rustc")] -fn translate_terminator_kind_call<'tcx, S: BaseState<'tcx> + HasMir<'tcx> + HasOwnerId>( +fn translate_terminator_kind_call<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>( s: &S, terminator: &rustc_middle::mir::TerminatorKind<'tcx>, ) -> TerminatorKind { @@ -435,7 +435,7 @@ fn translate_terminator_kind_call<'tcx, S: BaseState<'tcx> + HasMir<'tcx> + HasO } #[cfg(feature = "rustc")] -fn translate_terminator_kind_drop<'tcx, S: BaseState<'tcx> + HasMir<'tcx> + HasOwnerId>( +fn translate_terminator_kind_drop<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>( s: &S, terminator: &rustc_middle::mir::TerminatorKind<'tcx>, ) -> TerminatorKind { diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 952a80bbb..89465a036 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -44,7 +44,7 @@ where { let tcx = s.base().tcx; let rust_def_id = def_id.underlying_rust_def_id(); - let state_with_id = with_owner_id(s.base(), (), (), rust_def_id); + let state_with_id = s.with_owner_id(rust_def_id); let source_span; let attributes; let visibility; @@ -388,7 +388,7 @@ where S: BaseState<'tcx>, Body: IsBody + TypeMappable, { - let s = &with_owner_id(s.base(), (), (), def_id); + let s = &s.with_owner_id(def_id); let tcx = s.base().tcx; match get_def_kind(tcx, def_id) { RDefKind::Struct { .. } => FullDefKind::Struct { @@ -415,9 +415,11 @@ where let rustc_hir::ItemKind::TyAlias(_, _generics, ty) = &item.kind else { unreachable!() }; - let mut s = State::from_under_owner(s); - s.base.ty_alias_mode = true; - ty.sinto(&s) + let s = &s.with_base(Base { + ty_alias_mode: true, + ..s.base() + }); + ty.sinto(s) }), }, RDefKind::ForeignTy => FullDefKind::ForeignTy, @@ -519,8 +521,7 @@ where // Subtlety: we have to add the GAT arguments (if any) to the trait ref arguments. let args = item_args.rebase_onto(tcx, def_id, trait_ref.args); - let state_with_id = - with_owner_id(s.base(), (), (), impl_assoc.def_id); + let state_with_id = s.with_owner_id(impl_assoc.def_id); solve_item_implied_traits(&state_with_id, decl_def_id, args) }; @@ -539,7 +540,7 @@ where ty::GenericArgs::identity_for_item(tcx, decl_def_id); let args = item_args.rebase_onto(tcx, def_id, trait_ref.args); - let state_with_id = with_owner_id(s.base(), (), (), def_id); + let state_with_id = s.with_owner_id(def_id); solve_item_implied_traits(&state_with_id, decl_def_id, args) } else { // FIXME: For GATs, we need a param_env that has the arguments of @@ -1129,7 +1130,7 @@ fn drop_glue_shim<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> Option>(s: &S, def_id: RDefId) -> ParamEnv { let tcx = s.base().tcx; - let s = &with_owner_id(s.base(), (), (), def_id); + let s = &s.with_owner_id(def_id); ParamEnv { generics: tcx.generics_of(def_id).sinto(s), predicates: required_predicates(tcx, def_id, s.base().options.resolve_drop_bounds).sinto(s), diff --git a/frontend/exporter/src/types/thir.rs b/frontend/exporter/src/types/thir.rs index ceb61cdf4..0b7d7471c 100644 --- a/frontend/exporter/src/types/thir.rs +++ b/frontend/exporter/src/types/thir.rs @@ -804,7 +804,7 @@ pub enum ExprKind { }, #[custom_arm(FROM_TYPE::Closure(e) => { let (thir, expr_entrypoint) = get_thir(e.closure_id, gstate); - let s = &State::from_thir(gstate.base(), gstate.owner_id(), thir.clone()); + let s = &gstate.with_thir(thir.clone()); TO_TYPE::Closure { params: thir.params.raw.sinto(s), body: expr_entrypoint.sinto(s), @@ -858,7 +858,7 @@ pub trait ExprKindExt<'tcx> { &self, s: &S, ) -> (Option, Vec); - fn unroll_scope + HasThir<'tcx>>(&self, s: &S) -> thir::Expr<'tcx>; + fn unroll_scope + HasThir<'tcx>>(&self, s: &S) -> thir::Expr<'tcx>; } #[cfg(feature = "rustc")] @@ -875,7 +875,7 @@ impl<'tcx> ExprKindExt<'tcx> for thir::Expr<'tcx> { _ => (None, vec![]), } } - fn unroll_scope + HasThir<'tcx>>(&self, s: &S) -> thir::Expr<'tcx> { + fn unroll_scope + HasThir<'tcx>>(&self, s: &S) -> thir::Expr<'tcx> { // TODO: when we see a loop, we should lookup its label! label is actually a scope id // we remove scopes here, whence the TODO match self.kind { diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index 0a12b5348..6fc9f1e9c 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -1382,13 +1382,7 @@ where fn sinto(&self, s: &S) -> Binder { let bound_vars = self.bound_vars().sinto(s); let value = { - let under_binder_s = &State { - base: s.base(), - owner_id: s.owner_id(), - binder: self.as_ref().map_bound(|_| ()), - thir: (), - mir: (), - }; + let under_binder_s = &s.with_binder(self.as_ref().map_bound(|_| ())); self.as_ref().skip_binder().sinto(under_binder_s) }; Binder { value, bound_vars } @@ -1568,7 +1562,7 @@ fn get_container_for_assoc_item<'tcx, S: BaseState<'tcx>>( ) -> AssocItemContainer { let tcx = s.base().tcx; // We want to solve traits in the context of this item. - let state_with_id = &with_owner_id(s.base(), (), (), item.def_id); + let state_with_id = &s.with_owner_id(item.def_id); let container_id = item.container_id(tcx); match item.container { ty::AssocItemContainer::Trait => { From 8c3e3a757a0124531800e8d955747f3c016eb2fb Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 8 Jul 2025 15:15:45 +0200 Subject: [PATCH 15/51] Remove `HasXXXSetter` traits They weren't used anywhere. This also removes `IsState` which was an union of these traits. --- frontend/exporter/src/state.rs | 44 ++-------------------------------- 1 file changed, 2 insertions(+), 42 deletions(-) diff --git a/frontend/exporter/src/state.rs b/frontend/exporter/src/state.rs index 7a907d5fe..0c5653e39 100644 --- a/frontend/exporter/src/state.rs +++ b/frontend/exporter/src/state.rs @@ -12,52 +12,12 @@ macro_rules! mk_aux { self.$field.clone() } } - pub trait []<$($lts)*> { - type Out; - // fn []<$($lts,)*$($gen)*>(self: Self, $field: $($field_type)+<$($lts)*>) -> $state<$($params)*>; - fn [](self: Self, $field: $($field_type)+<$($lts)*>) -> Self::Out; - } - // const _: &str = stringify!( - #[allow(unused)] - impl<$($lts,)*$($gen_full)*> []<$($lts,)*> for $state<$($gen_full)*> { - type Out = $state<$($params)*>; - fn [](self: Self, $field: $($field_type)+<$($lts)*>) -> Self::Out { - let __this_field = $field; - let $state { $($fields,)* } = self; - let $field = __this_field; - $state { $($fields,)* } - } - } - // ); - // pub trait []<$($lts,)*$($gen_full)*> { - // fn [](self: Self, $field: $($field_type)+<$($lts)*>) -> $state<$($params)*>; - // } - // impl<$($lts,)*$($gen_full)*> []<$($lts,)*$($gen_full)*> for $state<$($gen_full)*> { - // fn [](self: Self, $field: $($field_type)+<$($lts)*>) -> $state<$($params)*> { - // let __this_field = $field; - // let $state { $($fields,)* } = self; - // let $field = __this_field; - // $state { $($fields,)* } - // } - // } } }; } -macro_rules! mk_is_state_trait { - ($lts:tt {$($finished:tt)*} {{$f0:ident, $($l:tt)*} $($f:tt)*} $($generic:tt)*) => { - paste! {mk_is_state_trait!{ - $lts {$($finished)* [] <$($l)*> +} {$($f)*} $($generic)* - // $lts {$($finished)* [] <$($l)* $($generic)*> +} {$($f)*} $($generic)* - }} - }; - ({$($glts:lifetime,)*} {$($finished:tt)*} {} $($generic:tt)*) => { - pub trait IsState<$($glts,)*> = $($finished)*; - }; -} macro_rules! mk { (struct $state:ident<$($glts:lifetime),*> {$($field:ident : {$($lts:lifetime),*} $field_type:ty),*$(,)?}) => { mk!(@$state {} {$($field)*} {$($field: {$($lts),*} {$field_type},)*}); - mk_is_state_trait!({$($glts,)*} {} {$({$field, $($lts,)*})*} $([<$field:camel>],)*); }; (@$state:ident {$($acc:tt)*} $fields:tt { $field:ident : $lts:tt $field_type:tt @@ -236,7 +196,7 @@ impl<'tcx> StateWithBase<'tcx> { } } -pub trait BaseState<'tcx>: IsState<'tcx> + HasBase<'tcx> + Clone { +pub trait BaseState<'tcx>: HasBase<'tcx> + Clone { /// Updates the OnwerId in a state, making sure to override `opt_def_id` in base as well. fn with_owner_id(&self, owner_id: rustc_hir::def_id::DefId) -> StateWithOwner<'tcx> { let mut base = self.base(); @@ -250,7 +210,7 @@ pub trait BaseState<'tcx>: IsState<'tcx> + HasBase<'tcx> + Clone { } } } -impl<'tcx, T: IsState<'tcx> + HasBase<'tcx> + Clone> BaseState<'tcx> for T {} +impl<'tcx, T: HasBase<'tcx> + Clone> BaseState<'tcx> for T {} /// State of anything below an `owner`. pub trait UnderOwnerState<'tcx>: BaseState<'tcx> + HasOwnerId { From 78946d15fe49ef4aa15d0e7ffc1f1998131d9d0b Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 10 Jul 2025 07:28:07 +0200 Subject: [PATCH 16/51] Reorder `State` fields --- frontend/exporter/src/state.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/exporter/src/state.rs b/frontend/exporter/src/state.rs index 0c5653e39..96a87ec96 100644 --- a/frontend/exporter/src/state.rs +++ b/frontend/exporter/src/state.rs @@ -163,9 +163,9 @@ mod types { mk!( struct State<'tcx> { base: {'tcx} types::Base, + owner_id: {} rustc_hir::def_id::DefId, thir: {'tcx} types::RcThir, mir: {'tcx} types::RcMir, - owner_id: {} rustc_hir::def_id::DefId, binder: {'tcx} types::UnitBinder, } ); @@ -173,13 +173,13 @@ mk!( pub use self::types::*; pub type StateWithBase<'tcx> = State, (), (), (), ()>; -pub type StateWithOwner<'tcx> = State, (), (), rustc_hir::def_id::DefId, ()>; +pub type StateWithOwner<'tcx> = State, rustc_hir::def_id::DefId, (), (), ()>; pub type StateWithBinder<'tcx> = - State, (), (), rustc_hir::def_id::DefId, types::UnitBinder<'tcx>>; + State, rustc_hir::def_id::DefId, (), (), types::UnitBinder<'tcx>>; pub type StateWithThir<'tcx> = - State, types::RcThir<'tcx>, (), rustc_hir::def_id::DefId, ()>; + State, rustc_hir::def_id::DefId, types::RcThir<'tcx>, (), ()>; pub type StateWithMir<'tcx> = - State, (), types::RcMir<'tcx>, rustc_hir::def_id::DefId, ()>; + State, rustc_hir::def_id::DefId, (), types::RcMir<'tcx>, ()>; impl<'tcx> StateWithBase<'tcx> { pub fn new( From 29ba2d6599592d23f9414f97dbd01229f6f8bfcd Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 10 Jul 2025 08:11:41 +0200 Subject: [PATCH 17/51] Track the type of surrounding expression in THIR translation --- frontend/exporter/src/state.rs | 43 +++++++++++++++++++++++------ frontend/exporter/src/types/thir.rs | 3 +- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/frontend/exporter/src/state.rs b/frontend/exporter/src/state.rs index 96a87ec96..a3937e330 100644 --- a/frontend/exporter/src/state.rs +++ b/frontend/exporter/src/state.rs @@ -167,19 +167,28 @@ mk!( thir: {'tcx} types::RcThir, mir: {'tcx} types::RcMir, binder: {'tcx} types::UnitBinder, + ty: {'tcx} rustc_middle::ty::Ty, } ); pub use self::types::*; -pub type StateWithBase<'tcx> = State, (), (), (), ()>; -pub type StateWithOwner<'tcx> = State, rustc_hir::def_id::DefId, (), (), ()>; +pub type StateWithBase<'tcx> = State, (), (), (), (), ()>; +pub type StateWithOwner<'tcx> = State, rustc_hir::def_id::DefId, (), (), (), ()>; pub type StateWithBinder<'tcx> = - State, rustc_hir::def_id::DefId, (), (), types::UnitBinder<'tcx>>; + State, rustc_hir::def_id::DefId, (), (), types::UnitBinder<'tcx>, ()>; pub type StateWithThir<'tcx> = - State, rustc_hir::def_id::DefId, types::RcThir<'tcx>, (), ()>; + State, rustc_hir::def_id::DefId, types::RcThir<'tcx>, (), (), ()>; +pub type StateWithThirAndTy<'tcx> = State< + Base<'tcx>, + rustc_hir::def_id::DefId, + types::RcThir<'tcx>, + (), + (), + rustc_middle::ty::Ty<'tcx>, +>; pub type StateWithMir<'tcx> = - State, rustc_hir::def_id::DefId, (), types::RcMir<'tcx>, ()>; + State, rustc_hir::def_id::DefId, (), types::RcMir<'tcx>, (), ()>; impl<'tcx> StateWithBase<'tcx> { pub fn new( @@ -187,11 +196,12 @@ impl<'tcx> StateWithBase<'tcx> { options: hax_frontend_exporter_options::Options, ) -> Self { Self { + base: Base::new(tcx, options), + owner_id: (), thir: (), mir: (), - owner_id: (), binder: (), - base: Base::new(tcx, options), + ty: (), } } } @@ -207,6 +217,7 @@ pub trait BaseState<'tcx>: HasBase<'tcx> + Clone { thir: (), mir: (), binder: (), + ty: (), } } } @@ -221,6 +232,7 @@ pub trait UnderOwnerState<'tcx>: BaseState<'tcx> + HasOwnerId { thir: (), mir: (), binder: (), + ty: (), } } fn with_binder(&self, binder: types::UnitBinder<'tcx>) -> StateWithBinder<'tcx> { @@ -230,6 +242,7 @@ pub trait UnderOwnerState<'tcx>: BaseState<'tcx> + HasOwnerId { binder, thir: (), mir: (), + ty: (), } } fn with_thir(&self, thir: types::RcThir<'tcx>) -> StateWithThir<'tcx> { @@ -239,6 +252,7 @@ pub trait UnderOwnerState<'tcx>: BaseState<'tcx> + HasOwnerId { thir, mir: (), binder: (), + ty: (), } } fn with_mir(&self, mir: types::RcMir<'tcx>) -> StateWithMir<'tcx> { @@ -248,6 +262,7 @@ pub trait UnderOwnerState<'tcx>: BaseState<'tcx> + HasOwnerId { mir, thir: (), binder: (), + ty: (), } } } @@ -258,7 +273,19 @@ pub trait UnderBinderState<'tcx> = UnderOwnerState<'tcx> + HasBinder<'tcx>; /// While translating expressions, we expect to always have a THIR /// body and an `owner_id` in the state -pub trait ExprState<'tcx> = UnderOwnerState<'tcx> + HasThir<'tcx>; +pub trait ExprState<'tcx>: UnderOwnerState<'tcx> + HasThir<'tcx> { + fn with_ty(&self, ty: rustc_middle::ty::Ty<'tcx>) -> StateWithThirAndTy<'tcx> { + State { + base: self.base(), + owner_id: self.owner_id(), + thir: self.thir(), + mir: (), + binder: (), + ty, + } + } +} +impl<'tcx, T> ExprState<'tcx> for T where T: UnderOwnerState<'tcx> + HasThir<'tcx> {} pub trait WithGlobalCacheExt<'tcx>: BaseState<'tcx> { /// Access the global cache. You must not call `sinto` within this function as this will likely diff --git a/frontend/exporter/src/types/thir.rs b/frontend/exporter/src/types/thir.rs index 0b7d7471c..62d7d68ba 100644 --- a/frontend/exporter/src/types/thir.rs +++ b/frontend/exporter/src/types/thir.rs @@ -190,6 +190,7 @@ impl<'tcx, S: ExprState<'tcx>> SInto for thir::StmtId { #[cfg(feature = "rustc")] impl<'tcx, S: ExprState<'tcx>> SInto for thir::Expr<'tcx> { fn sinto(&self, s: &S) -> Expr { + let s = &s.with_ty(self.ty); let (hir_id, attributes) = self.hir_id_and_attributes(s); let hir_id = hir_id.map(|hir_id| hir_id.index()); let unrolled = self.unroll_scope(s); @@ -589,7 +590,7 @@ pub type Expr = Decorated; /// Reflects [`thir::ExprKind`] #[derive(AdtInto)] -#[args(<'tcx, S: ExprState<'tcx>>, from: thir::ExprKind<'tcx>, state: S as gstate)] +#[args(<'tcx, S: ExprState<'tcx> + HasTy<'tcx>>, from: thir::ExprKind<'tcx>, state: S as gstate)] #[derive_group(Serializers)] #[derive(Clone, Debug, JsonSchema)] #[append( From ddae0abc2b8a7a8a6f25697f460d6f6f5583f837 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 10 Jul 2025 08:12:07 +0200 Subject: [PATCH 18/51] Add metadata information to unsize coercions --- engine/lib/import_thir.ml | 2 +- frontend/exporter/src/types/mir.rs | 42 +++++++++++++---- frontend/exporter/src/types/thir.rs | 11 +++++ frontend/exporter/src/types/ty.rs | 70 +++++++++++++++++++++++++++-- 4 files changed, 113 insertions(+), 12 deletions(-) diff --git a/engine/lib/import_thir.ml b/engine/lib/import_thir.ml index 44292f0dc..117368059 100644 --- a/engine/lib/import_thir.ml +++ b/engine/lib/import_thir.ml @@ -993,7 +993,7 @@ end) : EXPR = struct | ClosureFnPointer Safe | ReifyFnPointer -> (* we have arrow types, we do not distinguish between top-level functions and closures *) (c_expr source).e - | Unsize -> + | Unsize _ -> (* https://doc.rust-lang.org/std/marker/trait.Unsize.html *) (U.call Rust_primitives__unsize [ c_expr source ] span typ).e (* let source = c_expr source in *) diff --git a/frontend/exporter/src/types/mir.rs b/frontend/exporter/src/types/mir.rs index 2af9504e7..b615e7de1 100644 --- a/frontend/exporter/src/types/mir.rs +++ b/frontend/exporter/src/types/mir.rs @@ -863,8 +863,7 @@ pub enum AggregateKind { } #[derive_group(Serializers)] -#[derive(AdtInto, Clone, Debug, JsonSchema)] -#[args(<'tcx, S>, from: rustc_middle::mir::CastKind, state: S as _s)] +#[derive(Clone, Debug, JsonSchema)] pub enum CastKind { PointerExposeProvenance, PointerWithExposedProvenance, @@ -878,6 +877,32 @@ pub enum CastKind { Transmute, } +#[cfg(feature = "rustc")] +impl CastKind { + fn sfrom<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + kind: mir::CastKind, + src_ty: ty::Ty<'tcx>, + tgt_ty: ty::Ty<'tcx>, + ) -> CastKind { + match kind { + mir::CastKind::PointerExposeProvenance => CastKind::PointerExposeProvenance, + mir::CastKind::PointerWithExposedProvenance => CastKind::PointerWithExposedProvenance, + mir::CastKind::PointerCoercion(coercion, y) => { + let coercion = PointerCoercion::sfrom(s, coercion, src_ty, tgt_ty); + CastKind::PointerCoercion(coercion, y.sinto(s)) + } + mir::CastKind::IntToInt => CastKind::IntToInt, + mir::CastKind::FloatToInt => CastKind::FloatToInt, + mir::CastKind::FloatToFloat => CastKind::FloatToFloat, + mir::CastKind::IntToFloat => CastKind::IntToFloat, + mir::CastKind::PtrToPtr => CastKind::PtrToPtr, + mir::CastKind::FnPtrToPtr => CastKind::FnPtrToPtr, + mir::CastKind::Transmute => CastKind::Transmute, + } + } +} + #[derive_group(Serializers)] #[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S>, from: rustc_middle::mir::CoercionSource, state: S as _s)] @@ -902,17 +927,18 @@ pub enum NullOp { #[args(<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>, from: rustc_middle::mir::Rvalue<'tcx>, state: S as s)] pub enum Rvalue { Use(Operand), - #[custom_arm( - rustc_middle::mir::Rvalue::Repeat(op, ce) => { - let op = op.sinto(s); - Rvalue::Repeat(op, ce.sinto(s)) - }, - )] Repeat(Operand, ConstantExpr), Ref(Region, BorrowKind, Place), ThreadLocalRef(DefId), RawPtr(RawPtrKind, Place), Len(Place), + #[custom_arm( + FROM_TYPE::Cast(kind, op, tgt_ty) => { + let src_ty = op.ty(&*s.mir(), s.base().tcx); + let kind = CastKind::sfrom(s, *kind, src_ty, *tgt_ty); + TO_TYPE::Cast(kind, op.sinto(s), tgt_ty.sinto(s)) + }, + )] Cast(CastKind, Operand, Ty), BinaryOp(BinOp, (Operand, Operand)), NullaryOp(NullOp, Ty), diff --git a/frontend/exporter/src/types/thir.rs b/frontend/exporter/src/types/thir.rs index 62d7d68ba..c4435b1ff 100644 --- a/frontend/exporter/src/types/thir.rs +++ b/frontend/exporter/src/types/thir.rs @@ -705,6 +705,17 @@ pub enum ExprKind { NeverToAny { source: Expr, }, + #[custom_arm( + &FROM_TYPE::PointerCoercion { cast, source, .. } => { + let source = &gstate.thir().exprs[source]; + let src_ty = source.ty; + let tgt_ty = gstate.ty(); + TO_TYPE::PointerCoercion { + cast: PointerCoercion::sfrom(gstate, cast, src_ty, tgt_ty), + source: source.sinto(gstate), + } + }, + )] PointerCoercion { cast: PointerCoercion, source: Expr, diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index 6fc9f1e9c..a5144a2e6 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -1095,8 +1095,6 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for ty::AdtDef<'tcx> { } /// Reflects [`ty::adjustment::PointerCoercion`] -#[derive(AdtInto)] -#[args(, from: ty::adjustment::PointerCoercion, state: S as gstate)] #[derive_group(Serializers)] #[derive(Clone, Debug, JsonSchema)] pub enum PointerCoercion { @@ -1105,7 +1103,73 @@ pub enum PointerCoercion { ClosureFnPointer(Safety), MutToConstPointer, ArrayToPointer, - Unsize, + Unsize(UnsizingMetadata), +} + +/// The metadata to attach to the newly-unsized ptr. +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] +pub enum UnsizingMetadata { + Length(ConstantExpr), + VTablePtr(ImplExpr), + Unknown, +} + +#[cfg(feature = "rustc")] +impl PointerCoercion { + pub fn sfrom<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + coercion: ty::adjustment::PointerCoercion, + src_ty: ty::Ty<'tcx>, + tgt_ty: ty::Ty<'tcx>, + ) -> PointerCoercion { + match coercion { + ty::adjustment::PointerCoercion::ReifyFnPointer => PointerCoercion::ReifyFnPointer, + ty::adjustment::PointerCoercion::UnsafeFnPointer => PointerCoercion::UnsafeFnPointer, + ty::adjustment::PointerCoercion::ClosureFnPointer(x) => { + PointerCoercion::ClosureFnPointer(x.sinto(s)) + } + ty::adjustment::PointerCoercion::MutToConstPointer => { + PointerCoercion::MutToConstPointer + } + ty::adjustment::PointerCoercion::ArrayToPointer => PointerCoercion::ArrayToPointer, + ty::adjustment::PointerCoercion::Unsize => { + // We only support unsizing behind references, pointers and boxes for now. + let meta = match (src_ty.builtin_deref(true), tgt_ty.builtin_deref(true)) { + (Some(src_ty), Some(tgt_ty)) => { + let tcx = s.base().tcx; + let typing_env = s.typing_env(); + let (src_ty, tgt_ty) = + tcx.struct_lockstep_tails_raw(src_ty, tgt_ty, |ty| { + normalize(tcx, typing_env, ty) + }); + match tgt_ty.kind() { + ty::Slice(_) | ty::Str => match src_ty.kind() { + ty::Array(_, len) => { + let len = len.sinto(s); + UnsizingMetadata::Length(len) + } + _ => UnsizingMetadata::Unknown, + }, + ty::Dynamic(preds, ..) => { + let pred = preds[0].with_self_ty(tcx, src_ty); + let clause = pred.as_trait_clause().expect( + "the first `ExistentialPredicate` of `TyKind::Dynamic` \ + should be a trait clause", + ); + let tref = clause.rebind(clause.skip_binder().trait_ref); + let impl_expr = solve_trait(s, tref); + UnsizingMetadata::VTablePtr(impl_expr) + } + _ => UnsizingMetadata::Unknown, + } + } + _ => UnsizingMetadata::Unknown, + }; + PointerCoercion::Unsize(meta) + } + } + } } sinto_todo!(rustc_middle::ty, ScalarInt); From 88346de5647fe354426435062dc4aaa6a7830d16 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 10 Jul 2025 13:32:42 +0200 Subject: [PATCH 19/51] Never construct `ItemRef`s by hand --- frontend/exporter/src/traits.rs | 67 ++-------------------- frontend/exporter/src/traits/resolution.rs | 37 +++--------- frontend/exporter/src/types/ty.rs | 60 +++++++++++++++---- 3 files changed, 60 insertions(+), 104 deletions(-) diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index 1645b0daf..21ca8f842 100644 --- a/frontend/exporter/src/traits.rs +++ b/frontend/exporter/src/traits.rs @@ -52,18 +52,11 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for resolution: resolution::PathChunk::AssocItem { item, generic_args, - impl_exprs, predicate, index, .. } => ImplExprPathChunk::AssocItem { - item: ItemRef::new( - s, - item.def_id.sinto(s), - generic_args.sinto(s), - impl_exprs.sinto(s), - None, - ), + item: translate_item_ref(s, item.def_id, generic_args), assoc_item: item.sinto(s), predicate: predicate.sinto(s), predicate_id: <_ as SInto<_, Clause>>::sinto(predicate, s).id, @@ -88,14 +81,8 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for resolution: #[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema)] pub enum ImplExprAtom { /// A concrete `impl Trait for Type {}` item. - #[custom_arm(FROM_TYPE::Concrete { def_id, generics, impl_exprs } => TO_TYPE::Concrete( - ItemRef::new( - s, - def_id.sinto(s), - generics.sinto(s), - impl_exprs.sinto(s), - None, - ) + #[custom_arm(FROM_TYPE::Concrete { def_id, generics } => TO_TYPE::Concrete( + translate_item_ref(s, *def_id, generics), ),)] Concrete(ItemRef), /// A context-bound clause like `where T: Trait`. @@ -259,53 +246,7 @@ pub fn translate_item_ref<'tcx, S: UnderOwnerState<'tcx>>( def_id: RDefId, generics: ty::GenericArgsRef<'tcx>, ) -> ItemRef { - let key = (def_id, generics); - if let Some(item) = s.with_cache(|cache| cache.item_refs.get(&key).cloned()) { - return item; - } - let mut impl_exprs = solve_item_required_traits(s, def_id, generics); - let mut generic_args = generics.sinto(s); - - // If this is an associated item, resolve the trait reference. - let trait_info = self_clause_for_item(s, def_id, generics); - // Fixup the generics. - if let Some(tinfo) = &trait_info { - // The generics are split in two: the arguments of the trait and the arguments of the - // method. - // - // For instance, if we have: - // ``` - // trait Foo { - // fn baz(...) { ... } - // } - // - // fn test(x: T) { - // x.baz(...); - // ... - // } - // ``` - // The generics for the call to `baz` will be the concatenation: ``, which we - // split into `` and ``. - let trait_ref = tinfo.r#trait.hax_skip_binder_ref(); - let num_trait_generics = trait_ref.generic_args.len(); - generic_args.drain(0..num_trait_generics); - let num_trait_trait_clauses = trait_ref.impl_exprs.len(); - // Associated items take a `Self` clause as first clause, we skip that one too. Note: that - // clause is the same as `tinfo`. - impl_exprs.drain(0..num_trait_trait_clauses + 1); - } - - let content = ItemRefContents { - def_id: def_id.sinto(s), - generic_args, - impl_exprs, - in_trait: trait_info, - }; - let item = content.intern(s); - s.with_cache(|cache| { - cache.item_refs.insert(key, item.clone()); - }); - item + ItemRef::translate(s, def_id, generics) } /// Solve the trait obligations for a specific item use (for example, a method call, an ADT, etc.) diff --git a/frontend/exporter/src/traits/resolution.rs b/frontend/exporter/src/traits/resolution.rs index a13291898..159156042 100644 --- a/frontend/exporter/src/traits/resolution.rs +++ b/frontend/exporter/src/traits/resolution.rs @@ -20,16 +20,8 @@ use super::utils::{ pub enum PathChunk<'tcx> { AssocItem { item: AssocItem, - /// The arguments provided to the item (for GATs). + /// The arguments provided to the item (for GATs). Includes trait args. generic_args: GenericArgsRef<'tcx>, - /// The impl exprs that must be satisfied to apply the given arguments to the item. E.g. - /// `T: Clone` in the following example: - /// ```ignore - /// trait Foo { - /// type Type: Debug; - /// } - /// ``` - impl_exprs: Vec>, /// The implemented predicate. predicate: PolyTraitPredicate<'tcx>, /// The index of this predicate in the list returned by `implied_predicates`. @@ -50,8 +42,6 @@ pub enum ImplExprAtom<'tcx> { Concrete { def_id: DefId, generics: GenericArgsRef<'tcx>, - /// The impl exprs that prove the clauses on the impl. - impl_exprs: Vec>, }, /// A context-bound clause like `where T: Trait`. LocalBound { @@ -342,9 +332,7 @@ impl<'tcx> PredicateSearcher<'tcx> { let TyKind::Alias(AliasTyKind::Projection, alias_ty) = ty.skip_binder().kind() else { return Ok(()); }; - let (trait_ref, item_args) = alias_ty.trait_ref_and_own_args(tcx); - let item_args = tcx.mk_args(item_args); - let trait_ref = ty.rebind(trait_ref).upcast(tcx); + let trait_ref = ty.rebind(alias_ty.trait_ref(tcx)).upcast(tcx); // The predicate we're looking for is is `::Type: OtherTrait`. We look up `T as // Trait` in the current context and add all the bounds on `Trait::Type` to our context. @@ -362,10 +350,6 @@ impl<'tcx> PredicateSearcher<'tcx> { .map(|pred| EarlyBinder::bind(pred).instantiate(tcx, alias_ty.args)) .enumerate(); - // Resolve predicates required to mention the item. - let nested_impl_exprs = - self.resolve_item_required_predicates(alias_ty.def_id, alias_ty.args, warn)?; - // Add all the bounds on the corresponding associated item. self.extend(item_bounds.map(|(index, pred)| { let mut candidate = Candidate { @@ -375,8 +359,7 @@ impl<'tcx> PredicateSearcher<'tcx> { }; candidate.path.push(PathChunk::AssocItem { item: tcx.associated_item(alias_ty.def_id), - generic_args: item_args, - impl_exprs: nested_impl_exprs.clone(), + generic_args: alias_ty.args, predicate: pred, index, }); @@ -441,16 +424,10 @@ impl<'tcx> PredicateSearcher<'tcx> { impl_def_id, args: generics, .. - })) => { - // Resolve the predicates required by the impl. - let impl_exprs = - self.resolve_item_required_predicates(impl_def_id, generics, warn)?; - ImplExprAtom::Concrete { - def_id: impl_def_id, - generics, - impl_exprs, - } - } + })) => ImplExprAtom::Concrete { + def_id: impl_def_id, + generics, + }, Ok(ImplSource::Param(_)) => { match self.resolve_local(erased_tref.upcast(self.tcx), warn)? { Some(candidate) => candidate.into_impl_expr(tcx), diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index a5144a2e6..5f73a94ff 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -495,7 +495,7 @@ pub struct ItemRef { impl ItemRefContents { #[cfg(feature = "rustc")] - pub fn intern<'tcx, S: BaseState<'tcx>>(self, s: &S) -> ItemRef { + fn intern<'tcx, S: BaseState<'tcx>>(self, s: &S) -> ItemRef { s.with_global_cache(|cache| { let table_session = &mut cache.id_table_session; let contents = id_table::Node::new(self, table_session); @@ -506,20 +506,58 @@ impl ItemRefContents { impl ItemRef { #[cfg(feature = "rustc")] - pub fn new<'tcx, S: BaseState<'tcx>>( + pub fn translate<'tcx, S: UnderOwnerState<'tcx>>( s: &S, - def_id: DefId, - generic_args: Vec, - impl_exprs: Vec, - in_trait: Option, + def_id: RDefId, + generics: ty::GenericArgsRef<'tcx>, ) -> ItemRef { - let contents = ItemRefContents { - def_id, + let key = (def_id, generics); + if let Some(item) = s.with_cache(|cache| cache.item_refs.get(&key).cloned()) { + return item; + } + let mut impl_exprs = solve_item_required_traits(s, def_id, generics); + let mut generic_args = generics.sinto(s); + + // If this is an associated item, resolve the trait reference. + let trait_info = self_clause_for_item(s, def_id, generics); + // Fixup the generics. + if let Some(tinfo) = &trait_info { + // The generics are split in two: the arguments of the trait and the arguments of the + // method. + // + // For instance, if we have: + // ``` + // trait Foo { + // fn baz(...) { ... } + // } + // + // fn test(x: T) { + // x.baz(...); + // ... + // } + // ``` + // The generics for the call to `baz` will be the concatenation: ``, which we + // split into `` and ``. + let trait_ref = tinfo.r#trait.hax_skip_binder_ref(); + let num_trait_generics = trait_ref.generic_args.len(); + generic_args.drain(0..num_trait_generics); + let num_trait_trait_clauses = trait_ref.impl_exprs.len(); + // Associated items take a `Self` clause as first clause, we skip that one too. Note: that + // clause is the same as `tinfo`. + impl_exprs.drain(0..num_trait_trait_clauses + 1); + } + + let content = ItemRefContents { + def_id: def_id.sinto(s), generic_args, impl_exprs, - in_trait, + in_trait: trait_info, }; - contents.intern(s) + let item = content.intern(s); + s.with_cache(|cache| { + cache.item_refs.insert(key, item.clone()); + }); + item } pub fn contents(&self) -> &ItemRefContents { @@ -983,7 +1021,7 @@ pub enum TyKind { #[custom_arm(FROM_TYPE::Adt(adt_def, generics) => TO_TYPE::Adt(translate_item_ref(s, adt_def.did(), generics)),)] Adt(ItemRef), - #[custom_arm(FROM_TYPE::Foreign(def_id) => TO_TYPE::Foreign(ItemRef::new(s, def_id.sinto(s), vec![], vec![], None)),)] + #[custom_arm(FROM_TYPE::Foreign(def_id) => TO_TYPE::Foreign(translate_item_ref(s, *def_id, Default::default())),)] Foreign(ItemRef), Str, Array(Box, #[map(Box::new(x.sinto(s)))] Box), From 25795faa072543a518762214713472666ac232ca Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 10 Jul 2025 23:11:32 +0200 Subject: [PATCH 20/51] resolution: let `PredicateSearcher` index clauses itself In preparation for being able to insert new clauses after initial construction. --- frontend/exporter/src/traits/resolution.rs | 127 ++++++++++++--------- 1 file changed, 74 insertions(+), 53 deletions(-) diff --git a/frontend/exporter/src/traits/resolution.rs b/frontend/exporter/src/traits/resolution.rs index 159156042..cd0db4f0a 100644 --- a/frontend/exporter/src/traits/resolution.rs +++ b/frontend/exporter/src/traits/resolution.rs @@ -132,51 +132,44 @@ pub struct AnnotatedTraitPred<'tcx> { pub clause: PolyTraitPredicate<'tcx>, } +/// Returns the predicate to resolve as `Self`, if that makes sense in the current item. +/// Currently this predicate is only used inside trait declarations and their asosciated types. +fn initial_self_pred<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: rustc_span::def_id::DefId, +) -> Option> { + use DefKind::*; + let trait_def_id = match tcx.def_kind(def_id) { + Trait | TraitAlias => def_id, + // Hack: we don't support GATs well so for now we let assoc types refer to the + // implicit trait `Self` clause. Other associated items get an explicit `Self: + // Trait` clause passed to them so they don't need that. + AssocTy => tcx.parent(def_id), + _ => return None, + }; + let self_pred = self_predicate(tcx, trait_def_id).upcast(tcx); + Some(self_pred) +} + /// The predicates to use as a starting point for resolving trait references within this item. This -/// includes the "self" predicate if applicable and the `required_predicates` of this item and all -/// its parents, numbered starting from the parents. -fn initial_search_predicates<'tcx>( +/// includes the `required_predicates` of this item and all its parents. +fn local_bound_predicates<'tcx>( tcx: TyCtxt<'tcx>, def_id: rustc_span::def_id::DefId, add_drop: bool, -) -> Vec> { +) -> Vec> { fn acc_predicates<'tcx>( tcx: TyCtxt<'tcx>, def_id: rustc_span::def_id::DefId, add_drop: bool, - include_self_pred: bool, - predicates: &mut Vec>, - pred_id: &mut usize, + predicates: &mut Vec>, ) { - let next_item_origin = |pred_id: &mut usize| { - let origin = BoundPredicateOrigin::Item(*pred_id); - *pred_id += 1; - origin - }; use DefKind::*; match tcx.def_kind(def_id) { - // These inherit some predicates from their parent. - dk @ (AssocTy | AssocFn | AssocConst | Closure | Ctor(..) | Variant) => { + // These inherit predicates from their parent. + AssocTy | AssocFn | AssocConst | Closure | Ctor(..) | Variant => { let parent = tcx.parent(def_id); - // Hack: we don't support GATs well so for now we let assoc types refer to the - // implicit trait `Self` clause. Other associated items get an explicit `Self: - // Trait` clause passed to them so they don't need that. - let include_self_pred = include_self_pred && matches!(dk, AssocTy); - acc_predicates( - tcx, - parent, - add_drop, - include_self_pred, - predicates, - pred_id, - ); - } - Trait | TraitAlias if include_self_pred => { - let self_pred = self_predicate(tcx, def_id).upcast(tcx); - predicates.push(AnnotatedTraitPred { - origin: BoundPredicateOrigin::SelfPred, - clause: self_pred, - }) + acc_predicates(tcx, parent, add_drop, predicates); } _ => {} } @@ -184,17 +177,12 @@ fn initial_search_predicates<'tcx>( required_predicates(tcx, def_id, add_drop) .iter() .map(|(clause, _span)| *clause) - .filter_map(|clause| { - clause.as_trait_clause().map(|clause| AnnotatedTraitPred { - origin: next_item_origin(pred_id), - clause, - }) - }), + .filter_map(|clause| clause.as_trait_clause()), ); } let mut predicates = vec![]; - acc_predicates(tcx, def_id, add_drop, true, &mut predicates, &mut 0); + acc_predicates(tcx, def_id, add_drop, &mut predicates); predicates } @@ -248,6 +236,8 @@ pub struct PredicateSearcher<'tcx> { candidates: HashMap, Candidate<'tcx>>, /// Whether to add `T: Drop` bounds for every type generic and associated item. add_drop: bool, + /// Count the number of bound clauses in scope; used to identify clauses uniquely. + bound_clause_count: usize, } impl<'tcx> PredicateSearcher<'tcx> { @@ -261,22 +251,52 @@ impl<'tcx> PredicateSearcher<'tcx> { }, candidates: Default::default(), add_drop, + bound_clause_count: 0, }; - out.extend( - initial_search_predicates(tcx, owner_id, add_drop) - .into_iter() - .map(|clause| Candidate { - path: vec![], - pred: clause.clause, - origin: clause, - }), + out.insert_predicates( + initial_self_pred(tcx, owner_id).map(|clause| AnnotatedTraitPred { + origin: BoundPredicateOrigin::SelfPred, + clause, + }), ); + out.insert_bound_predicates(local_bound_predicates(tcx, owner_id, add_drop)); out } + /// Insert the bound clauses in the search context. Prefer inserting them all at once as this + /// will give priority to shorter resolution paths. Bound clauses are numbered from `0` in + /// insertion order. + pub fn insert_bound_predicates( + &mut self, + clauses: impl IntoIterator>, + ) { + let mut count = usize::MAX; + // Swap to avoid borrow conflicts. + std::mem::swap(&mut count, &mut self.bound_clause_count); + self.insert_predicates(clauses.into_iter().map(|clause| { + let i = count; + count += 1; + AnnotatedTraitPred { + origin: BoundPredicateOrigin::Item(i), + clause, + } + })); + std::mem::swap(&mut count, &mut self.bound_clause_count); + } + + /// Insert annotated predicates in the search context. Prefer inserting them all at once as + /// this will give priority to shorter resolution paths. + fn insert_predicates(&mut self, preds: impl IntoIterator>) { + self.insert_candidates(preds.into_iter().map(|clause| Candidate { + path: vec![], + pred: clause.clause, + origin: clause, + })) + } + /// Insert new candidates and all their parent predicates. This deduplicates predicates /// to avoid divergence. - fn extend(&mut self, candidates: impl IntoIterator>) { + fn insert_candidates(&mut self, candidates: impl IntoIterator>) { let tcx = self.tcx; // Filter out duplicated candidates. let mut new_candidates = Vec::new(); @@ -289,19 +309,20 @@ impl<'tcx> PredicateSearcher<'tcx> { } } if !new_candidates.is_empty() { - self.extend_parents(new_candidates); + // Insert the parents all at once. + self.insert_candidate_parents(new_candidates); } } /// Add the parents of these candidates. This is a separate function to avoid /// polymorphic recursion due to the closures capturing the type parameters of this /// function. - fn extend_parents(&mut self, new_candidates: Vec>) { + fn insert_candidate_parents(&mut self, new_candidates: Vec>) { let tcx = self.tcx; // Then recursively add their parents. This way ensures a breadth-first order, // which means we select the shortest path when looking up predicates. let add_drop = self.add_drop; - self.extend(new_candidates.into_iter().flat_map(|candidate| { + self.insert_candidates(new_candidates.into_iter().flat_map(|candidate| { parents_trait_predicates(tcx, candidate.pred, add_drop) .into_iter() .enumerate() @@ -351,7 +372,7 @@ impl<'tcx> PredicateSearcher<'tcx> { .enumerate(); // Add all the bounds on the corresponding associated item. - self.extend(item_bounds.map(|(index, pred)| { + self.insert_candidates(item_bounds.map(|(index, pred)| { let mut candidate = Candidate { path: trait_candidate.path.clone(), pred, From fac3d697f55dd847fbef8e1baae05046a4259aa8 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 11 Jul 2025 00:07:22 +0200 Subject: [PATCH 21/51] Resolve `dyn` projection predicates --- frontend/exporter/src/state.rs | 11 +++ frontend/exporter/src/traits.rs | 16 +--- frontend/exporter/src/traits/resolution.rs | 7 ++ frontend/exporter/src/types/ty.rs | 101 ++++++++++++++++++++- 4 files changed, 121 insertions(+), 14 deletions(-) diff --git a/frontend/exporter/src/state.rs b/frontend/exporter/src/state.rs index a3937e330..6258e0ad9 100644 --- a/frontend/exporter/src/state.rs +++ b/frontend/exporter/src/state.rs @@ -309,6 +309,17 @@ pub trait WithItemCacheExt<'tcx>: UnderOwnerState<'tcx> { fn with_cache(&self, f: impl FnOnce(&mut ItemCache<'tcx>) -> T) -> T { self.with_item_cache(self.owner_id(), f) } + fn with_predicate_searcher(&self, f: impl FnOnce(&mut PredicateSearcher<'tcx>) -> T) -> T { + self.with_cache(|cache| { + f(cache.predicate_searcher.get_or_insert_with(|| { + PredicateSearcher::new_for_owner( + self.base().tcx, + self.owner_id(), + self.base().options.resolve_drop_bounds, + ) + })) + }) + } } impl<'tcx, S: UnderOwnerState<'tcx>> WithItemCacheExt<'tcx> for S {} diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index 21ca8f842..a400b4ed1 100644 --- a/frontend/exporter/src/traits.rs +++ b/frontend/exporter/src/traits.rs @@ -1,7 +1,7 @@ use crate::prelude::*; #[cfg(feature = "rustc")] -mod resolution; +pub mod resolution; #[cfg(feature = "rustc")] mod utils; #[cfg(feature = "rustc")] @@ -218,18 +218,8 @@ pub fn solve_trait<'tcx, S: UnderOwnerState<'tcx>>( if let Some(impl_expr) = s.with_cache(|cache| cache.impl_exprs.get(&trait_ref).cloned()) { return impl_expr; } - let resolved = s.with_cache(|cache| { - cache - .predicate_searcher - .get_or_insert_with(|| { - PredicateSearcher::new_for_owner( - s.base().tcx, - s.owner_id(), - s.base().options.resolve_drop_bounds, - ) - }) - .resolve(&trait_ref, &warn) - }); + let resolved = + s.with_predicate_searcher(|pred_searcher| pred_searcher.resolve(&trait_ref, &warn)); let impl_expr = match resolved { Ok(x) => x.sinto(s), Err(e) => crate::fatal!(s, "{}", e), diff --git a/frontend/exporter/src/traits/resolution.rs b/frontend/exporter/src/traits/resolution.rs index cd0db4f0a..9633564bc 100644 --- a/frontend/exporter/src/traits/resolution.rs +++ b/frontend/exporter/src/traits/resolution.rs @@ -229,6 +229,7 @@ impl<'tcx> Candidate<'tcx> { } /// Stores a set of predicates along with where they came from. +#[derive(Clone)] pub struct PredicateSearcher<'tcx> { tcx: TyCtxt<'tcx>, typing_env: rustc_middle::ty::TypingEnv<'tcx>, @@ -284,6 +285,12 @@ impl<'tcx> PredicateSearcher<'tcx> { std::mem::swap(&mut count, &mut self.bound_clause_count); } + /// Override the param env; we use this when resolving `dyn` predicates to add more clauses to + /// the scope. + pub fn set_param_env(&mut self, param_env: ParamEnv<'tcx>) { + self.typing_env.param_env = param_env; + } + /// Insert annotated predicates in the search context. Prefer inserting them all at once as /// this will give priority to shorter resolution paths. fn insert_predicates(&mut self, preds: impl IntoIterator>) { diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index 5f73a94ff..b7da9bc65 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -1028,7 +1028,15 @@ pub enum TyKind { Slice(Box), RawPtr(Box, Mutability), Ref(Region, Box, Mutability), - Dynamic(Vec>, Region, DynKind), + #[custom_arm(FROM_TYPE::Dynamic(preds, region, _) => make_dyn(s, preds, region),)] + Dynamic( + /// Fresh type parameter that we use as the `Self` type in the prediates below. + ParamTy, + /// Clauses that define the trait object. These clauses use the fresh type parameter above + /// as `Self` type. + GenericPredicates, + Region, + ), #[custom_arm(FROM_TYPE::Coroutine(def_id, generics) => TO_TYPE::Coroutine(translate_item_ref(s, *def_id, generics)),)] Coroutine(ItemRef), Never, @@ -1045,6 +1053,97 @@ pub enum TyKind { Todo(String), } +/// Transform existential predicates into properly resolved predicates. +#[cfg(feature = "rustc")] +fn make_dyn<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + epreds: &'tcx ty::List>>, + region: &ty::Region<'tcx>, +) -> TyKind { + let tcx = s.base().tcx; + let def_id = s.owner_id(); + let span = rustc_span::DUMMY_SP.sinto(s); + + // Pretend there's an extra type in the environment. + let new_param_ty = { + let generics = tcx.generics_of(def_id); + let param_count = generics.parent_count + generics.own_params.len(); + ty::ParamTy::new(param_count as u32 + 1, rustc_span::Symbol::intern("_dyn")) + }; + let new_ty = new_param_ty.to_ty(tcx); + + // Set the new type as the `Self` parameter of our predicates. + let clauses: Vec> = epreds + .iter() + .map(|epred| epred.with_self_ty(tcx, new_ty)) + .collect(); + + // Populate a predicate searcher that knows about the `dyn` clauses. + let mut predicate_searcher = s.with_predicate_searcher(|ps| ps.clone()); + predicate_searcher + .insert_bound_predicates(clauses.iter().filter_map(|clause| clause.as_trait_clause())); + predicate_searcher.set_param_env(rustc_trait_selection::traits::normalize_param_env_or_error( + tcx, + ty::ParamEnv::new( + tcx.mk_clauses_from_iter( + s.param_env() + .caller_bounds() + .iter() + .chain(clauses.iter().copied()), + ), + ), + rustc_trait_selection::traits::ObligationCause::dummy(), + )); + + // Using the predicate searcher, translate the predicates. Only the projection predicates need + // to be handled specially. + let predicates = clauses + .into_iter() + .map(|clause| { + let clause = match clause.as_projection_clause() { + // Translate normally + None => clause.sinto(s), + // Translate by hand using our predicate searcher. This does the same as + // `clause.sinto(s)` except that it uses our predicate searcher to resolve the + // projection `ImplExpr`. + Some(proj) => { + let bound_vars = proj.bound_vars().sinto(s); + let proj = { + let alias_ty = &proj.skip_binder().projection_term.expect_ty(tcx); + let impl_expr = { + let poly_trait_ref = proj.rebind(alias_ty.trait_ref(tcx)); + predicate_searcher + .resolve(&poly_trait_ref, &|_| {}) + .s_unwrap(s) + .sinto(s) + }; + let Term::Ty(ty) = proj.skip_binder().term.sinto(s) else { + unreachable!() + }; + ProjectionPredicate { + impl_expr, + assoc_item: tcx.associated_item(alias_ty.def_id).sinto(s), + ty, + } + }; + let kind = Binder { + value: ClauseKind::Projection(proj), + bound_vars, + }; + let id = kind.clone().map(PredicateKind::Clause).predicate_id(); + Clause { kind, id } + } + }; + (clause, span.clone()) + }) + .collect(); + + let predicates = GenericPredicates { predicates }; + let param_ty = new_param_ty.sinto(s); + let region = region.sinto(s); + TyKind::Dynamic(param_ty, predicates, region) +} + /// Reflects [`ty::CanonicalUserTypeAnnotation`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::CanonicalUserTypeAnnotation<'tcx>, state: S as gstate)] From 3972a6c7d77314f86dcc931bdd7173fbb6aea892 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 11 Jul 2025 15:22:49 +0200 Subject: [PATCH 22/51] Fix `import_thir` after the `dyn` PR --- engine/lib/import_thir.ml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/engine/lib/import_thir.ml b/engine/lib/import_thir.ml index 117368059..2fcd89af0 100644 --- a/engine/lib/import_thir.ml +++ b/engine/lib/import_thir.ml @@ -1082,21 +1082,25 @@ end) : EXPR = struct | Error -> assertion_failure [ span ] "got type `Error`: Rust compilation probably failed." - | Dynamic (predicates, _region, Dyn) -> ( + | Dynamic (_, predicates, _region) -> ( let goals, non_traits = List.partition_map - ~f:(fun pred -> - match pred.value with - | Trait { args; def_id } -> + ~f:(fun ((clause, _span) : Types.clause * _) -> + match clause.kind.value with + | Trait { trait_ref; _ } -> let goal : dyn_trait_goal = { - trait = Concrete_ident.of_def_id ~value:false def_id; - non_self_args = List.map ~f:(c_generic_value span) args; + trait = + Concrete_ident.of_def_id ~value:false + trait_ref.value.def_id; + non_self_args = + List.map ~f:(c_generic_value span) + (List.tl_exn trait_ref.value.generic_args); } in First goal | _ -> Second ()) - predicates + predicates.predicates in match non_traits with | [] -> TDyn { witness = W.dyn; goals } From 9641a2993ec7fd516423618282e62f3a8f5b96a7 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 8 Jul 2025 17:33:11 +0200 Subject: [PATCH 23/51] full_def: inline `get_ctor_contents` --- frontend/exporter/src/types/new/full_def.rs | 50 +++++++++------------ 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 89465a036..7f6c1d307 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -676,7 +676,27 @@ where RDefKind::ConstParam => FullDefKind::ConstParam, RDefKind::LifetimeParam => FullDefKind::LifetimeParam, RDefKind::Variant => FullDefKind::Variant, - RDefKind::Ctor(ctor_of, _) => get_ctor_contents(s, ctor_of.sinto(s)), + RDefKind::Ctor(ctor_of, _) => { + let ctor_of = ctor_of.sinto(s); + + // The def_id of the adt this ctor belongs to. + let adt_def_id = match ctor_of { + CtorOf::Struct => tcx.parent(def_id), + CtorOf::Variant => tcx.parent(tcx.parent(def_id)), + }; + let adt_def = tcx.adt_def(adt_def_id); + let variant_id = adt_def.variant_index_with_ctor_id(def_id); + let fields = adt_def.variant(variant_id).fields.sinto(s); + let generic_args = ty::GenericArgs::identity_for_item(tcx, adt_def_id); + let output_ty = ty::Ty::new_adt(tcx, adt_def, generic_args).sinto(s); + FullDefKind::Ctor { + adt_def_id: adt_def_id.sinto(s), + ctor_of, + variant_id: variant_id.sinto(s), + fields, + output_ty, + } + } RDefKind::Field => FullDefKind::Field, RDefKind::Macro(kind) => FullDefKind::Macro(kind.sinto(s)), RDefKind::GlobalAsm => FullDefKind::GlobalAsm, @@ -1065,34 +1085,6 @@ where sig } -#[cfg(feature = "rustc")] -fn get_ctor_contents<'tcx, S, Body>(s: &S, ctor_of: CtorOf) -> FullDefKind -where - S: UnderOwnerState<'tcx>, - Body: IsBody + TypeMappable, -{ - let tcx = s.base().tcx; - let def_id = s.owner_id(); - - // The def_id of the adt this ctor belongs to. - let adt_def_id = match ctor_of { - CtorOf::Struct => tcx.parent(def_id), - CtorOf::Variant => tcx.parent(tcx.parent(def_id)), - }; - let adt_def = tcx.adt_def(adt_def_id); - let variant_id = adt_def.variant_index_with_ctor_id(def_id); - let fields = adt_def.variant(variant_id).fields.sinto(s); - let generic_args = ty::GenericArgs::identity_for_item(tcx, adt_def_id); - let output_ty = ty::Ty::new_adt(tcx, adt_def, generic_args).sinto(s); - FullDefKind::Ctor { - adt_def_id: adt_def_id.sinto(s), - ctor_of, - variant_id: variant_id.sinto(s), - fields, - output_ty, - } -} - #[cfg(feature = "rustc")] fn closure_once_shim<'tcx>( tcx: ty::TyCtxt<'tcx>, From a6be3d1c32a4e8a3a7c39699625f42199c47c199 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 8 Jul 2025 15:40:16 +0200 Subject: [PATCH 24/51] full_def: merge the three ADT types --- frontend/exporter/src/types/new/full_def.rs | 44 ++++++--------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 7f6c1d307..5893af445 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -179,20 +179,8 @@ pub struct ParamEnv { #[derive(Clone, Debug, JsonSchema)] pub enum FullDefKind { // Types - /// Refers to the struct definition, [`DefKind::Ctor`] refers to its constructor if it exists. - Struct { - param_env: ParamEnv, - def: AdtDef, - /// MIR body of the builtin `drop` impl. - drop_glue: Option, - }, - Union { - param_env: ParamEnv, - def: AdtDef, - /// MIR body of the builtin `drop` impl. - drop_glue: Option, - }, - Enum { + /// ADts (`Struct`, `Enum` and `Union` map to this variant). + Adt { param_env: ParamEnv, def: AdtDef, /// MIR body of the builtin `drop` impl. @@ -391,21 +379,13 @@ where let s = &s.with_owner_id(def_id); let tcx = s.base().tcx; match get_def_kind(tcx, def_id) { - RDefKind::Struct { .. } => FullDefKind::Struct { - param_env: get_param_env(s, def_id), - def: tcx.adt_def(def_id).sinto(s), - drop_glue: drop_glue_shim(tcx, def_id).and_then(|body| Body::from_mir(s, body)), - }, - RDefKind::Union { .. } => FullDefKind::Union { - param_env: get_param_env(s, def_id), - def: tcx.adt_def(def_id).sinto(s), - drop_glue: drop_glue_shim(tcx, def_id).and_then(|body| Body::from_mir(s, body)), - }, - RDefKind::Enum { .. } => FullDefKind::Enum { - param_env: get_param_env(s, def_id), - def: tcx.adt_def(def_id).sinto(s), - drop_glue: drop_glue_shim(tcx, def_id).and_then(|body| Body::from_mir(s, body)), - }, + RDefKind::Struct { .. } | RDefKind::Union { .. } | RDefKind::Enum { .. } => { + FullDefKind::Adt { + param_env: get_param_env(s, def_id), + def: tcx.adt_def(def_id).sinto(s), + drop_glue: drop_glue_shim(tcx, def_id).and_then(|body| Body::from_mir(s, body)), + } + } RDefKind::TyAlias { .. } => FullDefKind::TyAlias { param_env: get_param_env(s, def_id), ty: tcx.hir_get_if_local(def_id).map(|node| { @@ -780,9 +760,7 @@ impl FullDef { pub fn param_env(&self) -> Option<&ParamEnv> { use FullDefKind::*; match &self.kind { - Struct { param_env, .. } - | Union { param_env, .. } - | Enum { param_env, .. } + Adt { param_env, .. } | Trait { param_env, .. } | TraitAlias { param_env, .. } | TyAlias { param_env, .. } @@ -811,7 +789,7 @@ impl FullDef { Some((opt_ident.as_ref()?.0.clone(), def_id.clone())) }) .collect(), - FullDefKind::Enum { def, .. } => def + FullDefKind::Adt { def, .. } if matches!(def.adt_kind, AdtKind::Enum) => def .variants .raw .iter() From 00f4cf20bae2532a71a33effabb6a7e94e5231c7 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 8 Jul 2025 15:46:43 +0200 Subject: [PATCH 25/51] full_def: merge `AdtDef` into `FullDefKind` It's only used there and this will simplify what's coming. --- frontend/exporter/src/types/new/full_def.rs | 36 ++++++++++++++--- frontend/exporter/src/types/ty.rs | 45 +-------------------- 2 files changed, 32 insertions(+), 49 deletions(-) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 5893af445..2fb25b852 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -182,7 +182,10 @@ pub enum FullDefKind { /// ADts (`Struct`, `Enum` and `Union` map to this variant). Adt { param_env: ParamEnv, - def: AdtDef, + adt_kind: AdtKind, + variants: IndexVec, + flags: AdtFlags, + repr: ReprOptions, /// MIR body of the builtin `drop` impl. drop_glue: Option, }, @@ -380,9 +383,30 @@ where let tcx = s.base().tcx; match get_def_kind(tcx, def_id) { RDefKind::Struct { .. } | RDefKind::Union { .. } | RDefKind::Enum { .. } => { + let def = tcx.adt_def(def_id); + let variants = def + .variants() + .iter_enumerated() + .map(|(variant_idx, variant)| { + let discr = if def.is_enum() { + def.discriminant_for_variant(tcx, variant_idx) + } else { + // Structs and unions have a single variant. + assert_eq!(variant_idx.index(), 0); + ty::util::Discr { + val: 0, + ty: tcx.types.isize, + } + }; + VariantDef::sfrom(s, variant, discr) + }) + .collect(); FullDefKind::Adt { param_env: get_param_env(s, def_id), - def: tcx.adt_def(def_id).sinto(s), + adt_kind: def.adt_kind().sinto(s), + variants, + flags: def.flags().sinto(s), + repr: def.repr().sinto(s), drop_glue: drop_glue_shim(tcx, def_id).and_then(|body| Body::from_mir(s, body)), } } @@ -789,9 +813,11 @@ impl FullDef { Some((opt_ident.as_ref()?.0.clone(), def_id.clone())) }) .collect(), - FullDefKind::Adt { def, .. } if matches!(def.adt_kind, AdtKind::Enum) => def - .variants - .raw + FullDefKind::Adt { + adt_kind: AdtKind::Enum, + variants, + .. + } => variants .iter() .map(|variant| (variant.name.clone(), variant.def_id.clone())) .collect(), diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index b7da9bc65..1907e792e 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -352,7 +352,7 @@ pub struct VariantDef { #[cfg(feature = "rustc")] impl VariantDef { - fn sfrom<'tcx, S: UnderOwnerState<'tcx>>( + pub(crate) fn sfrom<'tcx, S: UnderOwnerState<'tcx>>( s: &S, def: &ty::VariantDef, discr_val: ty::util::Discr<'tcx>, @@ -1165,19 +1165,6 @@ pub enum AdtKind { Enum, } -// This comes from MIR -// TODO: add the generics and the predicates -/// Reflects [`ty::AdtDef`] -#[derive_group(Serializers)] -#[derive(Clone, Debug, JsonSchema)] -pub struct AdtDef { - pub did: DefId, - pub adt_kind: AdtKind, - pub variants: IndexVec, - pub flags: AdtFlags, - pub repr: ReprOptions, -} - sinto_todo!(rustc_middle::ty, AdtFlags); /// Reflects [`ty::ReprOptions`] @@ -1201,36 +1188,6 @@ sinto_todo!(rustc_abi, IntegerType); sinto_todo!(rustc_abi, ReprFlags); sinto_todo!(rustc_abi, Align); -#[cfg(feature = "rustc")] -impl<'tcx, S: UnderOwnerState<'tcx>> SInto for ty::AdtDef<'tcx> { - fn sinto(&self, s: &S) -> AdtDef { - let variants = self - .variants() - .iter_enumerated() - .map(|(variant_idx, variant)| { - let discr = if self.is_enum() { - self.discriminant_for_variant(s.base().tcx, variant_idx) - } else { - // Structs and unions have a single variant. - assert_eq!(variant_idx.index(), 0); - ty::util::Discr { - val: 0, - ty: s.base().tcx.types.isize, - } - }; - VariantDef::sfrom(s, variant, discr) - }) - .collect(); - AdtDef { - did: self.did().sinto(s), - adt_kind: self.adt_kind().sinto(s), - variants, - flags: self.flags().sinto(s), - repr: self.repr().sinto(s), - } - } -} - /// Reflects [`ty::adjustment::PointerCoercion`] #[derive_group(Serializers)] #[derive(Clone, Debug, JsonSchema)] From 83cc3e405827068f99b5455c9446bdc150df9171 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 8 Jul 2025 16:04:01 +0200 Subject: [PATCH 26/51] full_def: merge the various kinds of constant items --- frontend/exporter/src/types/new/full_def.rs | 74 ++++++++++----------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 2fb25b852..741144bc9 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -87,13 +87,11 @@ where let ty: Ty = body.local_decls[rustc_middle::mir::Local::ZERO] .ty .sinto(&state_with_id); - // Promoted constants only happen within MIR bodies; we can therefore assume that - // `Body` is a MIR body and unwrap. - let body = Body::from_mir(&state_with_id, body).s_unwrap(s); - kind = FullDefKind::PromotedConst { + kind = FullDefKind::Const { param_env, ty, - body, + kind: ConstKind::PromotedConst, + body: Body::from_mir(&state_with_id, body), }; // None of these make sense for a promoted constant. @@ -174,6 +172,20 @@ pub struct ParamEnv { pub predicates: GenericPredicates, } +/// The kind of a constant item. +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] +pub enum ConstKind { + /// Top-level constant: `const CONST: usize = 42;` + TopLevel, + /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]` + AnonConst, + /// An inline constant, e.g. `const { 1 + 2 }` + InlineConst, + /// A promoted constant, e.g. the `1 + 2` in `&(1 + 2)` + PromotedConst, +} + /// Imbues [`rustc_hir::def::DefKind`] with a lot of extra information. #[derive_group(Serializers)] #[derive(Clone, Debug, JsonSchema)] @@ -288,6 +300,7 @@ pub enum FullDefKind { Const { param_env: ParamEnv, ty: Ty, + kind: ConstKind, body: Option, }, /// Associated constant: `trait MyTrait { const ASSOC: usize; }` @@ -298,24 +311,6 @@ pub enum FullDefKind { ty: Ty, body: Option, }, - /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]` - AnonConst { - param_env: ParamEnv, - ty: Ty, - body: Option, - }, - /// An inline constant, e.g. `const { 1 + 2 }` - InlineConst { - param_env: ParamEnv, - ty: Ty, - body: Option, - }, - /// A promoted constant, e.g. `&(1 + 2)` - PromotedConst { - param_env: ParamEnv, - ty: Ty, - body: Body, - }, Static { param_env: ParamEnv, /// Whether it's a `unsafe static`, `safe static` (inside extern only) or just a `static`. @@ -633,11 +628,22 @@ where .then(|| virtual_impl_for(s, ty::TraitRef::new(tcx, fn_trait, trait_args))), } } - RDefKind::Const { .. } => FullDefKind::Const { - param_env: get_param_env(s, def_id), - ty: tcx.type_of(def_id).instantiate_identity().sinto(s), - body: Body::body(def_id, s), - }, + kind @ (RDefKind::Const { .. } + | RDefKind::AnonConst { .. } + | RDefKind::InlineConst { .. }) => { + let kind = match kind { + RDefKind::Const { .. } => ConstKind::TopLevel, + RDefKind::AnonConst { .. } => ConstKind::AnonConst, + RDefKind::InlineConst { .. } => ConstKind::InlineConst, + _ => unreachable!(), + }; + FullDefKind::Const { + param_env: get_param_env(s, def_id), + ty: tcx.type_of(def_id).instantiate_identity().sinto(s), + kind, + body: Body::body(def_id, s), + } + } RDefKind::AssocConst { .. } => FullDefKind::AssocConst { parent: tcx.parent(def_id).sinto(s), param_env: get_param_env(s, def_id), @@ -645,16 +651,6 @@ where ty: tcx.type_of(def_id).instantiate_identity().sinto(s), body: Body::body(def_id, s), }, - RDefKind::AnonConst { .. } => FullDefKind::AnonConst { - param_env: get_param_env(s, def_id), - ty: tcx.type_of(def_id).instantiate_identity().sinto(s), - body: Body::body(def_id, s), - }, - RDefKind::InlineConst { .. } => FullDefKind::InlineConst { - param_env: get_param_env(s, def_id), - ty: tcx.type_of(def_id).instantiate_identity().sinto(s), - body: Body::body(def_id, s), - }, RDefKind::Static { safety, mutability, @@ -793,8 +789,6 @@ impl FullDef { | AssocFn { param_env, .. } | Const { param_env, .. } | AssocConst { param_env, .. } - | AnonConst { param_env, .. } - | InlineConst { param_env, .. } | Static { param_env, .. } | TraitImpl { param_env, .. } | InherentImpl { param_env, .. } => Some(param_env), From d4762a3864178169c23a8afeacb64030082b024f Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 10 Jul 2025 13:46:08 +0200 Subject: [PATCH 27/51] full_def: remove `parent` fields It's redundant, we already have this information in `DefId`. --- frontend/exporter/src/types/new/full_def.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 741144bc9..f275d0503 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -17,8 +17,6 @@ type DefaultFullDefBody = MirBody; #[derive(Clone, Debug, JsonSchema)] pub struct FullDef { pub def_id: DefId, - /// The enclosing item. - pub parent: Option, /// The span of the definition of this item (e.g. for a function this is is signature). pub span: Span, /// The span of the whole definition (including e.g. the function body). @@ -107,7 +105,6 @@ where .and_then(|source_span| tcx.sess.source_map().span_to_snippet(source_span).ok()); FullDef { def_id: def_id.clone(), - parent: def_id.parent.clone(), span: def_id.def_span(s), source_span: source_span.sinto(s), source_text, @@ -211,7 +208,6 @@ pub enum FullDefKind { ForeignTy, /// Associated type: `trait MyTrait { type Assoc; }` AssocTy { - parent: DefId, param_env: ParamEnv, implied_predicates: GenericPredicates, associated_item: AssocItem, @@ -268,7 +264,6 @@ pub enum FullDefKind { /// Associated function: `impl MyStruct { fn associated() {} }` or `trait Foo { fn associated() /// {} }` AssocFn { - parent: DefId, param_env: ParamEnv, associated_item: AssocItem, inline: InlineAttr, @@ -305,7 +300,6 @@ pub enum FullDefKind { }, /// Associated constant: `trait MyTrait { const ASSOC: usize; }` AssocConst { - parent: DefId, param_env: ParamEnv, associated_item: AssocItem, ty: Ty, @@ -423,7 +417,6 @@ where }, RDefKind::ForeignTy => FullDefKind::ForeignTy, RDefKind::AssocTy { .. } => FullDefKind::AssocTy { - parent: tcx.parent(def_id).sinto(s), param_env: get_param_env(s, def_id), implied_predicates: implied_predicates( tcx, @@ -591,7 +584,6 @@ where body: Body::body(def_id, s), }, RDefKind::AssocFn { .. } => FullDefKind::AssocFn { - parent: tcx.parent(def_id).sinto(s), param_env: get_param_env(s, def_id), associated_item: tcx.associated_item(def_id).sinto(s), inline: tcx.codegen_fn_attrs(def_id).inline.sinto(s), @@ -645,7 +637,6 @@ where } } RDefKind::AssocConst { .. } => FullDefKind::AssocConst { - parent: tcx.parent(def_id).sinto(s), param_env: get_param_env(s, def_id), associated_item: tcx.associated_item(def_id).sinto(s), ty: tcx.type_of(def_id).instantiate_identity().sinto(s), From 2d7e20fe0dd20ea75a75cb7bc9be4978a7a55c04 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 10 Jul 2025 13:55:46 +0200 Subject: [PATCH 28/51] full_def: move heavy rustc logic to `rustc_utils` --- frontend/exporter/src/rustc_utils.rs | 196 +++++++++++++++- frontend/exporter/src/types/new/full_def.rs | 246 +++----------------- 2 files changed, 227 insertions(+), 215 deletions(-) diff --git a/frontend/exporter/src/rustc_utils.rs b/frontend/exporter/src/rustc_utils.rs index 1d7f51bfc..cb6ae4c6a 100644 --- a/frontend/exporter/src/rustc_utils.rs +++ b/frontend/exporter/src/rustc_utils.rs @@ -1,5 +1,6 @@ use crate::prelude::*; -use rustc_middle::ty; +use rustc_hir::def::DefKind as RDefKind; +use rustc_middle::{mir, ty}; #[extension_traits::extension(pub trait SubstBinder)] impl<'tcx, T: ty::TypeFoldable>> ty::Binder<'tcx, T> { @@ -114,3 +115,196 @@ pub fn get_closest_parent_type( _ => get_closest_parent_type(tcx, tcx.parent(id)), } } + +/// Gets the visibility (`pub` or not) of the definition. Returns `None` for defs that don't have a +/// meaningful visibility. +pub fn get_def_visibility<'tcx>( + tcx: ty::TyCtxt<'tcx>, + def_id: RDefId, + def_kind: RDefKind, +) -> Option { + use RDefKind::*; + match def_kind { + AssocConst + | AssocFn + | Const + | Enum + | Field + | Fn + | ForeignTy + | Macro { .. } + | Mod + | Static { .. } + | Struct + | Trait + | TraitAlias + | TyAlias { .. } + | Union + | Use + | Variant => Some(tcx.visibility(def_id).is_public()), + // These kinds don't have visibility modifiers (which would cause `visibility` to panic). + AnonConst + | AssocTy + | Closure + | ConstParam + | Ctor { .. } + | ExternCrate + | ForeignMod + | GlobalAsm + | Impl { .. } + | InlineConst + | LifetimeParam + | OpaqueTy + | SyntheticCoroutineBody + | TyParam => None, + } +} + +/// Gets the attributes of the definition. +pub fn get_def_attrs<'tcx>( + tcx: ty::TyCtxt<'tcx>, + def_id: RDefId, + def_kind: RDefKind, +) -> &'tcx [rustc_hir::Attribute] { + use RDefKind::*; + match def_kind { + // These kinds cause `get_attrs_unchecked` to panic. + ConstParam | LifetimeParam | TyParam | ForeignMod => &[], + _ => tcx.get_attrs_unchecked(def_id), + } +} + +/// Gets the children of a module. +pub fn get_mod_children<'tcx>( + tcx: ty::TyCtxt<'tcx>, + def_id: RDefId, +) -> Vec<(Option, RDefId)> { + match def_id.as_local() { + Some(ldid) => match tcx.hir_node_by_def_id(ldid) { + rustc_hir::Node::Crate(m) + | rustc_hir::Node::Item(&rustc_hir::Item { + kind: rustc_hir::ItemKind::Mod(_, m), + .. + }) => m + .item_ids + .iter() + .map(|&item_id| { + let opt_ident = tcx.hir_item(item_id).kind.ident(); + let def_id = item_id.owner_id.to_def_id(); + (opt_ident, def_id) + }) + .collect(), + node => panic!("DefKind::Module is an unexpected node: {node:?}"), + }, + None => tcx + .module_children(def_id) + .iter() + .map(|child| (Some(child.ident), child.res.def_id())) + .collect(), + } +} + +/// Gets the children of an `extern` block. Empty if the block is not defined in the current crate. +pub fn get_foreign_mod_children<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> Vec { + match def_id.as_local() { + Some(ldid) => tcx + .hir_node_by_def_id(ldid) + .expect_item() + .expect_foreign_mod() + .1 + .iter() + .map(|foreign_item_ref| foreign_item_ref.id.owner_id.to_def_id()) + .collect(), + None => vec![], + } +} + +/// The signature of a method impl may be a subtype of the one expected from the trait decl, as in +/// the example below. For correctness, we must be able to map from the method generics declared in +/// the trait to the actual method generics. Because this would require type inference, we instead +/// simply return the declared signature. This will cause issues if it is possible to use such a +/// more-specific implementation with its more-specific type, but we have a few other issues with +/// lifetime-generic function pointers anyway so this is unlikely to cause problems. +/// +/// ```ignore +/// trait MyCompare: Sized { +/// fn compare(self, other: Other) -> bool; +/// } +/// impl<'a> MyCompare<&'a ()> for &'a () { +/// // This implementation is more general because it works for non-`'a` refs. Note that only +/// // late-bound vars may differ in this way. +/// // `<&'a () as MyCompare<&'a ()>>::compare` has type `fn<'b>(&'a (), &'b ()) -> bool`, +/// // but type `fn(&'a (), &'a ()) -> bool` was expected from the trait declaration. +/// fn compare<'b>(self, _other: &'b ()) -> bool { +/// true +/// } +/// } +/// ``` +pub fn get_method_sig<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> ty::PolyFnSig<'tcx> { + let real_sig = tcx.fn_sig(def_id).instantiate_identity(); + let item = tcx.associated_item(def_id); + if !matches!(item.container, ty::AssocItemContainer::Impl) { + return real_sig; + } + let Some(decl_method_id) = item.trait_item_def_id else { + return real_sig; + }; + let declared_sig = tcx.fn_sig(decl_method_id); + + // TODO(Nadrieril): Temporary hack: if the signatures have the same number of bound vars, we + // keep the real signature. While the declared signature is more correct, it is also less + // normalized and we can't normalize without erasing regions but regions are crucial in + // function signatures. Hence we cheat here, until charon gains proper normalization + // capabilities. + if declared_sig.skip_binder().bound_vars().len() == real_sig.bound_vars().len() { + return real_sig; + } + + let impl_def_id = item.container_id(tcx); + // The trait predicate that is implemented by the surrounding impl block. + let implemented_trait_ref = tcx + .impl_trait_ref(impl_def_id) + .unwrap() + .instantiate_identity(); + // Construct arguments for the declared method generics in the context of the implemented + // method generics. + let impl_args = ty::GenericArgs::identity_for_item(tcx, def_id); + let decl_args = impl_args.rebase_onto(tcx, impl_def_id, implemented_trait_ref.args); + let sig = declared_sig.instantiate(tcx, decl_args); + // Avoids accidentally using the same lifetime name twice in the same scope + // (once in impl parameters, second in the method declaration late-bound vars). + let sig = tcx.anonymize_bound_vars(sig); + sig +} + +pub fn closure_once_shim<'tcx>( + tcx: ty::TyCtxt<'tcx>, + closure_ty: ty::Ty<'tcx>, +) -> Option> { + let ty::Closure(def_id, args) = closure_ty.kind() else { + unreachable!() + }; + let instance = match args.as_closure().kind() { + ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { + ty::Instance::fn_once_adapter_instance(tcx, *def_id, args) + } + ty::ClosureKind::FnOnce => return None, + }; + let mir = tcx.instance_mir(instance.def).clone(); + let mir = ty::EarlyBinder::bind(mir).instantiate(tcx, instance.args); + Some(mir) +} + +pub fn drop_glue_shim<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> Option> { + let drop_in_place = + tcx.require_lang_item(rustc_hir::LangItem::DropInPlace, rustc_span::DUMMY_SP); + if !tcx.generics_of(def_id).is_empty() { + // Hack: layout code panics if it can't fully normalize types, which can happen e.g. with a + // trait associated type. For now we only translate the glue for monomorphic types. + return None; + } + let ty = tcx.type_of(def_id).instantiate_identity(); + let instance_kind = ty::InstanceKind::DropGlue(drop_in_place, Some(ty)); + let mir = tcx.instance_mir(instance_kind).clone(); + Some(mir) +} diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index f275d0503..fe1d953f9 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -4,7 +4,7 @@ use std::sync::Arc; #[cfg(feature = "rustc")] use rustc_hir::def::DefKind as RDefKind; #[cfg(feature = "rustc")] -use rustc_middle::{mir, ty}; +use rustc_middle::ty; #[cfg(feature = "rustc")] use rustc_span::def_id::DefId as RDefId; @@ -391,16 +391,16 @@ where }) .collect(); FullDefKind::Adt { - param_env: get_param_env(s, def_id), + param_env: get_param_env(s), adt_kind: def.adt_kind().sinto(s), variants, flags: def.flags().sinto(s), repr: def.repr().sinto(s), - drop_glue: drop_glue_shim(tcx, def_id).and_then(|body| Body::from_mir(s, body)), + drop_glue: get_drop_glue_shim(s), } } RDefKind::TyAlias { .. } => FullDefKind::TyAlias { - param_env: get_param_env(s, def_id), + param_env: get_param_env(s), ty: tcx.hir_get_if_local(def_id).map(|node| { let rustc_hir::Node::Item(item) = node else { unreachable!() @@ -417,7 +417,7 @@ where }, RDefKind::ForeignTy => FullDefKind::ForeignTy, RDefKind::AssocTy { .. } => FullDefKind::AssocTy { - param_env: get_param_env(s, def_id), + param_env: get_param_env(s), implied_predicates: implied_predicates( tcx, def_id, @@ -433,7 +433,7 @@ where }, RDefKind::OpaqueTy => FullDefKind::OpaqueTy, RDefKind::Trait { .. } => FullDefKind::Trait { - param_env: get_param_env(s, def_id), + param_env: get_param_env(s), implied_predicates: implied_predicates( tcx, def_id, @@ -451,7 +451,7 @@ where .collect::>(), }, RDefKind::TraitAlias { .. } => FullDefKind::TraitAlias { - param_env: get_param_env(s, def_id), + param_env: get_param_env(s), implied_predicates: implied_predicates( tcx, def_id, @@ -462,7 +462,7 @@ where }, RDefKind::Impl { .. } => { use std::collections::HashMap; - let param_env = get_param_env(s, def_id); + let param_env = get_param_env(s); match tcx.impl_subject(def_id).instantiate_identity() { ty::ImplSubject::Inherent(ty) => { let items = tcx @@ -577,18 +577,18 @@ where } } RDefKind::Fn { .. } => FullDefKind::Fn { - param_env: get_param_env(s, def_id), + param_env: get_param_env(s), inline: tcx.codegen_fn_attrs(def_id).inline.sinto(s), is_const: tcx.constness(def_id) == rustc_hir::Constness::Const, sig: tcx.fn_sig(def_id).instantiate_identity().sinto(s), body: Body::body(def_id, s), }, RDefKind::AssocFn { .. } => FullDefKind::AssocFn { - param_env: get_param_env(s, def_id), + param_env: get_param_env(s), associated_item: tcx.associated_item(def_id).sinto(s), inline: tcx.codegen_fn_attrs(def_id).inline.sinto(s), is_const: tcx.constness(def_id) == rustc_hir::Constness::Const, - sig: get_method_sig(s).sinto(s), + sig: get_method_sig(tcx, def_id).sinto(s), body: Body::body(def_id, s), }, RDefKind::Closure { .. } => { @@ -607,9 +607,8 @@ where FullDefKind::Closure { is_const: tcx.constness(def_id) == rustc_hir::Constness::Const, args: ClosureArgs::sfrom(s, def_id, closure), - once_shim: closure_once_shim(tcx, closure_ty) - .and_then(|body| Body::from_mir(s, body)), - drop_glue: drop_glue_shim(tcx, def_id).and_then(|body| Body::from_mir(s, body)), + once_shim: get_closure_once_shim(s, closure_ty), + drop_glue: get_drop_glue_shim(s), fn_once_impl: virtual_impl_for( s, ty::TraitRef::new(tcx, fn_once_trait, trait_args), @@ -630,14 +629,14 @@ where _ => unreachable!(), }; FullDefKind::Const { - param_env: get_param_env(s, def_id), + param_env: get_param_env(s), ty: tcx.type_of(def_id).instantiate_identity().sinto(s), kind, body: Body::body(def_id, s), } } RDefKind::AssocConst { .. } => FullDefKind::AssocConst { - param_env: get_param_env(s, def_id), + param_env: get_param_env(s), associated_item: tcx.associated_item(def_id).sinto(s), ty: tcx.type_of(def_id).instantiate_identity().sinto(s), body: Body::body(def_id, s), @@ -648,7 +647,7 @@ where nested, .. } => FullDefKind::Static { - param_env: get_param_env(s, def_id), + param_env: get_param_env(s), safety: safety.sinto(s), mutability: mutability.sinto(s), nested: nested.sinto(s), @@ -858,113 +857,6 @@ impl ImplAssocItem { } } -/// Gets the visibility (`pub` or not) of the definition. Returns `None` for defs that don't have a -/// meaningful visibility. -#[cfg(feature = "rustc")] -fn get_def_visibility<'tcx>( - tcx: ty::TyCtxt<'tcx>, - def_id: RDefId, - def_kind: RDefKind, -) -> Option { - use RDefKind::*; - match def_kind { - AssocConst - | AssocFn - | Const - | Enum - | Field - | Fn - | ForeignTy - | Macro { .. } - | Mod - | Static { .. } - | Struct - | Trait - | TraitAlias - | TyAlias { .. } - | Union - | Use - | Variant => Some(tcx.visibility(def_id).is_public()), - // These kinds don't have visibility modifiers (which would cause `visibility` to panic). - AnonConst - | AssocTy - | Closure - | ConstParam - | Ctor { .. } - | ExternCrate - | ForeignMod - | GlobalAsm - | Impl { .. } - | InlineConst - | LifetimeParam - | OpaqueTy - | SyntheticCoroutineBody - | TyParam => None, - } -} - -/// Gets the attributes of the definition. -#[cfg(feature = "rustc")] -fn get_def_attrs<'tcx>( - tcx: ty::TyCtxt<'tcx>, - def_id: RDefId, - def_kind: RDefKind, -) -> &'tcx [rustc_hir::Attribute] { - use RDefKind::*; - match def_kind { - // These kinds cause `get_attrs_unchecked` to panic. - ConstParam | LifetimeParam | TyParam | ForeignMod => &[], - _ => tcx.get_attrs_unchecked(def_id), - } -} - -/// Gets the children of a module. -#[cfg(feature = "rustc")] -fn get_mod_children<'tcx>( - tcx: ty::TyCtxt<'tcx>, - def_id: RDefId, -) -> Vec<(Option, RDefId)> { - match def_id.as_local() { - Some(ldid) => match tcx.hir_node_by_def_id(ldid) { - rustc_hir::Node::Crate(m) - | rustc_hir::Node::Item(&rustc_hir::Item { - kind: rustc_hir::ItemKind::Mod(_, m), - .. - }) => m - .item_ids - .iter() - .map(|&item_id| { - let opt_ident = tcx.hir_item(item_id).kind.ident(); - let def_id = item_id.owner_id.to_def_id(); - (opt_ident, def_id) - }) - .collect(), - node => panic!("DefKind::Module is an unexpected node: {node:?}"), - }, - None => tcx - .module_children(def_id) - .iter() - .map(|child| (Some(child.ident), child.res.def_id())) - .collect(), - } -} - -/// Gets the children of an `extern` block. Empty if the block is not defined in the current crate. -#[cfg(feature = "rustc")] -fn get_foreign_mod_children<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> Vec { - match def_id.as_local() { - Some(ldid) => tcx - .hir_node_by_def_id(ldid) - .expect_item() - .expect_foreign_mod() - .1 - .iter() - .map(|foreign_item_ref| foreign_item_ref.id.owner_id.to_def_id()) - .collect(), - None => vec![], - } -} - #[cfg(feature = "rustc")] fn get_self_predicate<'tcx, S: UnderOwnerState<'tcx>>(s: &S) -> TraitPredicate { use ty::Upcast; @@ -1010,108 +902,34 @@ where }) } -/// The signature of a method impl may be a subtype of the one expected from the trait decl, as in -/// the example below. For correctness, we must be able to map from the method generics declared in -/// the trait to the actual method generics. Because this would require type inference, we instead -/// simply return the declared signature. This will cause issues if it is possible to use such a -/// more-specific implementation with its more-specific type, but we have a few other issues with -/// lifetime-generic function pointers anyway so this is unlikely to cause problems. -/// -/// ```ignore -/// trait MyCompare: Sized { -/// fn compare(self, other: Other) -> bool; -/// } -/// impl<'a> MyCompare<&'a ()> for &'a () { -/// // This implementation is more general because it works for non-`'a` refs. Note that only -/// // late-bound vars may differ in this way. -/// // `<&'a () as MyCompare<&'a ()>>::compare` has type `fn<'b>(&'a (), &'b ()) -> bool`, -/// // but type `fn(&'a (), &'a ()) -> bool` was expected from the trait declaration. -/// fn compare<'b>(self, _other: &'b ()) -> bool { -/// true -/// } -/// } -/// ``` #[cfg(feature = "rustc")] -fn get_method_sig<'tcx, S>(s: &S) -> ty::PolyFnSig<'tcx> +fn get_closure_once_shim<'tcx, S, Body>(s: &S, closure_ty: ty::Ty<'tcx>) -> Option where S: UnderOwnerState<'tcx>, + Body: IsBody + TypeMappable, { let tcx = s.base().tcx; - let def_id = s.owner_id(); - let real_sig = tcx.fn_sig(def_id).instantiate_identity(); - let item = tcx.associated_item(def_id); - if !matches!(item.container, ty::AssocItemContainer::Impl) { - return real_sig; - } - let Some(decl_method_id) = item.trait_item_def_id else { - return real_sig; - }; - let declared_sig = tcx.fn_sig(decl_method_id); - - // TODO(Nadrieril): Temporary hack: if the signatures have the same number of bound vars, we - // keep the real signature. While the declared signature is more correct, it is also less - // normalized and we can't normalize without erasing regions but regions are crucial in - // function signatures. Hence we cheat here, until charon gains proper normalization - // capabilities. - if declared_sig.skip_binder().bound_vars().len() == real_sig.bound_vars().len() { - return real_sig; - } - - let impl_def_id = item.container_id(tcx); - // The trait predicate that is implemented by the surrounding impl block. - let implemented_trait_ref = tcx - .impl_trait_ref(impl_def_id) - .unwrap() - .instantiate_identity(); - // Construct arguments for the declared method generics in the context of the implemented - // method generics. - let impl_args = ty::GenericArgs::identity_for_item(tcx, def_id); - let decl_args = impl_args.rebase_onto(tcx, impl_def_id, implemented_trait_ref.args); - let sig = declared_sig.instantiate(tcx, decl_args); - // Avoids accidentally using the same lifetime name twice in the same scope - // (once in impl parameters, second in the method declaration late-bound vars). - let sig = tcx.anonymize_bound_vars(sig); - sig + let mir = crate::closure_once_shim(tcx, closure_ty)?; + let body = Body::from_mir(s, mir)?; + Some(body) } #[cfg(feature = "rustc")] -fn closure_once_shim<'tcx>( - tcx: ty::TyCtxt<'tcx>, - closure_ty: ty::Ty<'tcx>, -) -> Option> { - let ty::Closure(def_id, args) = closure_ty.kind() else { - unreachable!() - }; - let instance = match args.as_closure().kind() { - ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { - ty::Instance::fn_once_adapter_instance(tcx, *def_id, args) - } - ty::ClosureKind::FnOnce => return None, - }; - let mir = tcx.instance_mir(instance.def).clone(); - let mir = ty::EarlyBinder::bind(mir).instantiate(tcx, instance.args); - Some(mir) -} - -#[cfg(feature = "rustc")] -fn drop_glue_shim<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> Option> { - let drop_in_place = - tcx.require_lang_item(rustc_hir::LangItem::DropInPlace, rustc_span::DUMMY_SP); - if !tcx.generics_of(def_id).is_empty() { - // Hack: layout code panics if it can't fully normalize types, which can happen e.g. with a - // trait associated type. For now we only translate the glue for monomorphic types. - return None; - } - let ty = tcx.type_of(def_id).instantiate_identity(); - let instance_kind = ty::InstanceKind::DropGlue(drop_in_place, Some(ty)); - let mir = tcx.instance_mir(instance_kind).clone(); - Some(mir) +fn get_drop_glue_shim<'tcx, S, Body>(s: &S) -> Option +where + S: UnderOwnerState<'tcx>, + Body: IsBody + TypeMappable, +{ + let tcx = s.base().tcx; + let mir = crate::drop_glue_shim(tcx, s.owner_id())?; + let body = Body::from_mir(s, mir)?; + Some(body) } #[cfg(feature = "rustc")] -fn get_param_env<'tcx, S: BaseState<'tcx>>(s: &S, def_id: RDefId) -> ParamEnv { +fn get_param_env<'tcx, S: UnderOwnerState<'tcx>>(s: &S) -> ParamEnv { let tcx = s.base().tcx; - let s = &s.with_owner_id(def_id); + let def_id = s.owner_id(); ParamEnv { generics: tcx.generics_of(def_id).sinto(s), predicates: required_predicates(tcx, def_id, s.base().options.resolve_drop_bounds).sinto(s), From 9d12de035d5f7068ebc9e3d4a2a5dd96fcb01cef Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 10 Jul 2025 14:00:42 +0200 Subject: [PATCH 29/51] full_def: add helper --- frontend/exporter/src/types/new/full_def.rs | 28 ++++++++------------- 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index fe1d953f9..b6d7f0d60 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -418,12 +418,7 @@ where RDefKind::ForeignTy => FullDefKind::ForeignTy, RDefKind::AssocTy { .. } => FullDefKind::AssocTy { param_env: get_param_env(s), - implied_predicates: implied_predicates( - tcx, - def_id, - s.base().options.resolve_drop_bounds, - ) - .sinto(s), + implied_predicates: get_implied_predicates(s), associated_item: tcx.associated_item(def_id).sinto(s), value: if tcx.defaultness(def_id).has_value() { Some(tcx.type_of(def_id).instantiate_identity().sinto(s)) @@ -434,12 +429,7 @@ where RDefKind::OpaqueTy => FullDefKind::OpaqueTy, RDefKind::Trait { .. } => FullDefKind::Trait { param_env: get_param_env(s), - implied_predicates: implied_predicates( - tcx, - def_id, - s.base().options.resolve_drop_bounds, - ) - .sinto(s), + implied_predicates: get_implied_predicates(s), self_predicate: get_self_predicate(s), items: tcx .associated_items(def_id) @@ -452,12 +442,7 @@ where }, RDefKind::TraitAlias { .. } => FullDefKind::TraitAlias { param_env: get_param_env(s), - implied_predicates: implied_predicates( - tcx, - def_id, - s.base().options.resolve_drop_bounds, - ) - .sinto(s), + implied_predicates: get_implied_predicates(s), self_predicate: get_self_predicate(s), }, RDefKind::Impl { .. } => { @@ -935,3 +920,10 @@ fn get_param_env<'tcx, S: UnderOwnerState<'tcx>>(s: &S) -> ParamEnv { predicates: required_predicates(tcx, def_id, s.base().options.resolve_drop_bounds).sinto(s), } } + +#[cfg(feature = "rustc")] +fn get_implied_predicates<'tcx, S: UnderOwnerState<'tcx>>(s: &S) -> GenericPredicates { + let tcx = s.base().tcx; + let def_id = s.owner_id(); + implied_predicates(tcx, def_id, s.base().options.resolve_drop_bounds).sinto(s) +} From e91aedb6fc5767fedeb824a178938957b191b19e Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 10 Jul 2025 14:51:57 +0200 Subject: [PATCH 30/51] full_def: better way to translate type aliases --- frontend/exporter/src/types/new/full_def.rs | 29 ++++++++------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index b6d7f0d60..0ad2c004c 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -201,8 +201,7 @@ pub enum FullDefKind { /// Type alias: `type Foo = Bar;` TyAlias { param_env: ParamEnv, - /// `Some` if the item is in the local crate. - ty: Option, + ty: Ty, }, /// Type from an `extern` block. ForeignTy, @@ -399,22 +398,16 @@ where drop_glue: get_drop_glue_shim(s), } } - RDefKind::TyAlias { .. } => FullDefKind::TyAlias { - param_env: get_param_env(s), - ty: tcx.hir_get_if_local(def_id).map(|node| { - let rustc_hir::Node::Item(item) = node else { - unreachable!() - }; - let rustc_hir::ItemKind::TyAlias(_, _generics, ty) = &item.kind else { - unreachable!() - }; - let s = &s.with_base(Base { - ty_alias_mode: true, - ..s.base() - }); - ty.sinto(s) - }), - }, + RDefKind::TyAlias { .. } => { + let s = &s.with_base(Base { + ty_alias_mode: true, + ..s.base() + }); + FullDefKind::TyAlias { + param_env: get_param_env(s), + ty: tcx.type_of(def_id).instantiate_identity().sinto(s), + } + } RDefKind::ForeignTy => FullDefKind::ForeignTy, RDefKind::AssocTy { .. } => FullDefKind::AssocTy { param_env: get_param_env(s), From e837a1a41eba79808a898ec92da0dc8b6f09201d Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 18 Jul 2025 15:04:31 +0200 Subject: [PATCH 31/51] full_def: provide virtual impl for `Drop` --- frontend/exporter/src/types/new/full_def.rs | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 0ad2c004c..daf7a309d 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -197,6 +197,8 @@ pub enum FullDefKind { repr: ReprOptions, /// MIR body of the builtin `drop` impl. drop_glue: Option, + /// Info required to construct a virtual `Drop` impl for this adt. + drop_impl: Box, }, /// Type alias: `type Foo = Bar;` TyAlias { @@ -288,6 +290,8 @@ pub enum FullDefKind { once_shim: Option, /// MIR body of the builtin `drop` impl. drop_glue: Option, + /// Info required to construct a virtual `Drop` impl for this closure. + drop_impl: Box, }, // Constants @@ -389,6 +393,8 @@ where VariantDef::sfrom(s, variant, discr) }) .collect(); + + let drop_trait = tcx.lang_items().drop_trait().unwrap(); FullDefKind::Adt { param_env: get_param_env(s), adt_kind: def.adt_kind().sinto(s), @@ -396,6 +402,14 @@ where flags: def.flags().sinto(s), repr: def.repr().sinto(s), drop_glue: get_drop_glue_shim(s), + drop_impl: virtual_impl_for( + s, + ty::TraitRef::new( + tcx, + drop_trait, + [tcx.type_of(def_id).instantiate_identity()], + ), + ), } } RDefKind::TyAlias { .. } => { @@ -582,11 +596,20 @@ where let fn_once_trait = tcx.lang_items().fn_once_trait().unwrap(); let fn_mut_trait = tcx.lang_items().fn_mut_trait().unwrap(); let fn_trait = tcx.lang_items().fn_trait().unwrap(); + let drop_trait = tcx.lang_items().drop_trait().unwrap(); FullDefKind::Closure { is_const: tcx.constness(def_id) == rustc_hir::Constness::Const, args: ClosureArgs::sfrom(s, def_id, closure), once_shim: get_closure_once_shim(s, closure_ty), drop_glue: get_drop_glue_shim(s), + drop_impl: virtual_impl_for( + s, + ty::TraitRef::new( + tcx, + drop_trait, + [tcx.type_of(def_id).instantiate_identity()], + ), + ), fn_once_impl: virtual_impl_for( s, ty::TraitRef::new(tcx, fn_once_trait, trait_args), From f3a3e1c251e8821268455de44b5d9da5cf37b47b Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 18 Jul 2025 15:27:54 +0200 Subject: [PATCH 32/51] Tweak the representation of special `ImplExpr`s for `Drop` --- engine/lib/import_thir.ml | 7 +- frontend/exporter/src/traits.rs | 22 +++++-- frontend/exporter/src/traits/resolution.rs | 75 ++++++++++++++-------- 3 files changed, 69 insertions(+), 35 deletions(-) diff --git a/engine/lib/import_thir.ml b/engine/lib/import_thir.ml index 2fcd89af0..15f06cf20 100644 --- a/engine/lib/import_thir.ml +++ b/engine/lib/import_thir.ml @@ -1122,7 +1122,7 @@ end) : EXPR = struct and c_impl_expr (span : Thir.span) (ie : Thir.impl_expr) : impl_expr = let goal = c_trait_ref span ie.trait.value in - let impl = { kind = c_impl_expr_atom span ie.impl; goal } in + let impl = { kind = c_impl_expr_atom span ie.impl goal; goal } in match ie.impl with | Concrete { value = { impl_exprs = []; _ }; _ } -> impl | Concrete { value = { impl_exprs; _ }; _ } -> @@ -1135,7 +1135,7 @@ end) : EXPR = struct let args = List.map ~f:(c_generic_value span) tr.value.generic_args in { trait; args } - and c_impl_expr_atom (span : Thir.span) (ie : Thir.impl_expr_atom) : + and c_impl_expr_atom (span : Thir.span) (ie : Thir.impl_expr_atom) goal : impl_expr_kind = let browse_path (item_kind : impl_expr_kind) (chunk : Thir.impl_expr_path_chunk) = @@ -1168,8 +1168,7 @@ end) : EXPR = struct List.fold ~init ~f:browse_path path | Dyn -> Dyn | SelfImpl { path; _ } -> List.fold ~init:Self ~f:browse_path path - | Builtin { trait; _ } -> Builtin (c_trait_ref span trait.value) - | Drop _ -> failwith @@ "impl_expr_atom: Drop" + | Builtin _ -> Builtin goal | Error str -> failwith @@ "impl_expr_atom: Error " ^ str and c_generic_value (span : Thir.span) (ty : Thir.generic_arg) : generic_value diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index a400b4ed1..cb079454e 100644 --- a/frontend/exporter/src/traits.rs +++ b/frontend/exporter/src/traits.rs @@ -112,16 +112,12 @@ pub enum ImplExprAtom { /// `dyn Trait` implements `Trait` using a built-in implementation; this refers to that /// built-in implementation. Dyn, - /// A virtual `Drop` implementation. - /// `Drop` doesn't work like a real trait but we want to pretend it does. If a type has a - /// user-defined `impl Drop for X` we just use the `Concrete` variant, but if it doesn't we use - /// this variant to supply the data needed to know what code will run on drop. - Drop(DropData), /// A built-in trait whose implementation is computed by the compiler, such as `FnMut`. This /// morally points to an invisible `impl` block; as such it contains the information we may /// need from one. Builtin { - r#trait: Binder, + /// Extra data for the given trait. + trait_data: BuiltinTraitData, /// The `ImplExpr`s required to satisfy the implied predicates on the trait declaration. /// E.g. since `FnMut: FnOnce`, a built-in `T: FnMut` impl would have an `ImplExpr` for `T: /// FnOnce`. @@ -133,6 +129,20 @@ pub enum ImplExprAtom { Error(String), } +#[derive(AdtInto)] +#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: resolution::BuiltinTraitData<'tcx>, state: S as s)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema)] +pub enum BuiltinTraitData { + /// A virtual `Drop` implementation. + /// `Drop` doesn't work like a real trait but we want to pretend it does. If a type has a + /// user-defined `impl Drop for X` we just use the `Concrete` variant, but if it doesn't we use + /// this variant to supply the data needed to know what code will run on drop. + Drop(DropData), + /// Some other builtin trait. + Other, +} + #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: resolution::DropData<'tcx>, state: S as s)] #[derive_group(Serializers)] diff --git a/frontend/exporter/src/traits/resolution.rs b/frontend/exporter/src/traits/resolution.rs index 9633564bc..99a9ccfd3 100644 --- a/frontend/exporter/src/traits/resolution.rs +++ b/frontend/exporter/src/traits/resolution.rs @@ -64,16 +64,12 @@ pub enum ImplExprAtom<'tcx> { /// `dyn Trait` implements `Trait` using a built-in implementation; this refers to that /// built-in implementation. Dyn, - /// A virtual `Drop` implementation. - /// `Drop` doesn't work like a real trait but we want to pretend it does. If a type has a - /// user-defined `impl Drop for X` we just use the `Concrete` variant, but if it doesn't we use - /// this variant to supply the data needed to know what code will run on drop. - Drop(DropData<'tcx>), /// A built-in trait whose implementation is computed by the compiler, such as `FnMut`. This /// morally points to an invisible `impl` block; as such it contains the information we may /// need from one. Builtin { - r#trait: PolyTraitRef<'tcx>, + /// Extra data for the given trait. + trait_data: BuiltinTraitData<'tcx>, /// The `ImplExpr`s required to satisfy the implied predicates on the trait declaration. /// E.g. since `FnMut: FnOnce`, a built-in `T: FnMut` impl would have an `ImplExpr` for `T: /// FnOnce`. @@ -85,6 +81,17 @@ pub enum ImplExprAtom<'tcx> { Error(String), } +#[derive(Debug, Clone)] +pub enum BuiltinTraitData<'tcx> { + /// A virtual `Drop` implementation. + /// `Drop` doesn't work like a real trait but we want to pretend it does. If a type has a + /// user-defined `impl Drop for X` we just use the `Concrete` variant, but if it doesn't we use + /// this variant to supply the data needed to know what code will run on drop. + Drop(DropData<'tcx>), + /// Some other builtin trait. + Other, +} + #[derive(Debug, Clone)] pub enum DropData<'tcx> { /// A drop that does nothing, e.g. for scalars and pointers. @@ -446,6 +453,14 @@ impl<'tcx> PredicateSearcher<'tcx> { let erased_tref = normalize_bound_val(self.tcx, self.typing_env, *tref); let trait_def_id = erased_tref.skip_binder().def_id; + let error = |msg: String| { + warn(&msg); + Ok(ImplExpr { + r#impl: ImplExprAtom::Error(msg), + r#trait: *tref, + }) + }; + let impl_source = shallow_resolve_trait_ref(tcx, self.typing_env.param_env, erased_tref); let atom = match impl_source { Ok(ImplSource::UserDefined(ImplSourceUserDefinedData { @@ -463,8 +478,7 @@ impl<'tcx> PredicateSearcher<'tcx> { let msg = format!( "Could not find a clause for `{tref:?}` in the item parameters" ); - warn(&msg); - ImplExprAtom::Error(msg) + return error(msg); } } } @@ -511,7 +525,7 @@ impl<'tcx> PredicateSearcher<'tcx> { }) .collect(); ImplExprAtom::Builtin { - r#trait: *tref, + trait_data: BuiltinTraitData::Other, impl_exprs, types, } @@ -537,7 +551,7 @@ impl<'tcx> PredicateSearcher<'tcx> { // TODO: how to check if there is a real drop impl????? let ty = erased_tref.skip_binder().args[0].as_type().unwrap(); // Source of truth are `ty::needs_drop_components` and `tcx.needs_drop_raw`. - match ty.kind() { + let drop_data = match ty.kind() { // TODO: Does `UnsafeBinder` drop its contents? ty::Bool | ty::Char @@ -551,14 +565,14 @@ impl<'tcx> PredicateSearcher<'tcx> { | ty::FnDef(..) | ty::FnPtr(..) | ty::UnsafeBinder(..) - | ty::Never => ImplExprAtom::Drop(DropData::Noop), + | ty::Never => Ok(DropData::Noop), ty::Array(inner_ty, _) | ty::Pat(inner_ty, _) | ty::Slice(inner_ty) => { - ImplExprAtom::Drop(DropData::Glue { + Ok(DropData::Glue { ty, impl_exprs: vec![resolve_drop(*inner_ty)?], }) } - ty::Tuple(tys) => ImplExprAtom::Drop(DropData::Glue { + ty::Tuple(tys) => Ok(DropData::Glue { ty, impl_exprs: tys.iter().map(resolve_drop).try_collect()?, }), @@ -566,14 +580,13 @@ impl<'tcx> PredicateSearcher<'tcx> { // We should have been able to resolve the `T: Drop` clause above, if we // get here we don't know how to reconstruct the arguments to the impl. let msg = format!("Cannot resolve clause `{tref:?}`"); - warn(&msg); - ImplExprAtom::Error(msg) + return error(msg); } ty::Adt(_, args) | ty::Closure(_, args) | ty::Coroutine(_, args) | ty::CoroutineClosure(_, args) - | ty::CoroutineWitness(_, args) => ImplExprAtom::Drop(DropData::Glue { + | ty::CoroutineWitness(_, args) => Ok(DropData::Glue { ty, impl_exprs: args .iter() @@ -583,22 +596,21 @@ impl<'tcx> PredicateSearcher<'tcx> { }), // Every `dyn` has a `Drop` in its vtable, ergo we pretend that every `dyn` has // `Drop` in its list of traits. - ty::Dynamic(..) => ImplExprAtom::Dyn, + ty::Dynamic(..) => Err(ImplExprAtom::Dyn), ty::Param(..) | ty::Alias(..) | ty::Bound(..) => { if self.add_drop { // We've added `Drop` impls on everything, we should be able to resolve // it. match self.resolve_local(erased_tref.upcast(self.tcx), warn)? { - Some(candidate) => candidate.into_impl_expr(tcx), + Some(candidate) => Err(candidate.into_impl_expr(tcx)), None => { let msg = format!("Cannot find virtual `Drop` clause: `{tref:?}`"); - warn(&msg); - ImplExprAtom::Error(msg) + return error(msg); } } } else { - ImplExprAtom::Drop(DropData::Implicit) + Ok(DropData::Implicit) } } @@ -607,9 +619,23 @@ impl<'tcx> PredicateSearcher<'tcx> { "Cannot resolve clause `{tref:?}` \ because of a type error" ); - warn(&msg); - ImplExprAtom::Error(msg) + return error(msg); + } + }; + match drop_data { + Ok(drop_data) => { + let impl_exprs = self.resolve_item_implied_predicates( + trait_def_id, + erased_tref.skip_binder().args, + warn, + )?; + ImplExprAtom::Builtin { + trait_data: BuiltinTraitData::Drop(drop_data), + impl_exprs, + types: vec![], + } } + Err(atom) => atom, } } Err(e) => { @@ -617,8 +643,7 @@ impl<'tcx> PredicateSearcher<'tcx> { "Could not find a clause for `{tref:?}` \ in the current context: `{e:?}`" ); - warn(&msg); - ImplExprAtom::Error(msg) + return error(msg); } }; From 773fc143bbd2104316e5e0bd40af321d20d88247 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 19 Jul 2025 23:32:29 +0200 Subject: [PATCH 33/51] Fix equality on `Ty` --- frontend/exporter/src/id_table.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/exporter/src/id_table.rs b/frontend/exporter/src/id_table.rs index d13d87358..3e2cb47ea 100644 --- a/frontend/exporter/src/id_table.rs +++ b/frontend/exporter/src/id_table.rs @@ -88,7 +88,7 @@ impl SupportedType for ItemRefContents { } /// A node is a bundle of an ID with a value. -#[derive(Deserialize, Serialize, Debug, JsonSchema, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Deserialize, Serialize, Debug, JsonSchema, PartialOrd, Ord)] #[serde(into = "serde_repr::NodeRepr")] #[serde(try_from = "serde_repr::NodeRepr")] pub struct Node> { @@ -111,6 +111,12 @@ impl + Hash> Hash for Node { self.value.as_ref().hash(state); } } +impl + Eq> Eq for Node {} +impl + PartialEq> PartialEq for Node { + fn eq(&self, other: &Self) -> bool { + self.value == other.value + } +} /// Manual implementation of `Clone` that doesn't require a `Clone` /// bound on `T`. From 0af2fc52064e7849b6b223a4cec1125a98c7520c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 17 Jul 2025 16:00:05 +0200 Subject: [PATCH 34/51] full_def: don't store entire `FullDef`s in assoc items This makes monomorphization harder --- frontend/exporter/src/types/new/full_def.rs | 66 +++++++-------------- 1 file changed, 22 insertions(+), 44 deletions(-) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index daf7a309d..37c973342 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -1,5 +1,4 @@ use crate::prelude::*; -use std::sync::Arc; #[cfg(feature = "rustc")] use rustc_hir::def::DefKind as RDefKind; @@ -7,6 +6,8 @@ use rustc_hir::def::DefKind as RDefKind; use rustc_middle::ty; #[cfg(feature = "rustc")] use rustc_span::def_id::DefId as RDefId; +#[cfg(feature = "rustc")] +use std::sync::Arc; /// Hack: charon used to rely on the old `()` default everywhere. To avoid big merge conflicts with /// in-flight PRs we're changing the default here. Eventually this should be removed. @@ -224,7 +225,7 @@ pub enum FullDefKind { /// The special `Self: Trait` clause. self_predicate: TraitPredicate, /// Associated items, in definition order. - items: Vec<(AssocItem, Arc>)>, + items: Vec, }, /// Trait alias: `trait IntIterator = Iterator;` TraitAlias { @@ -244,14 +245,14 @@ pub enum FullDefKind { /// ``` implied_impl_exprs: Vec, /// Associated items, in the order of the trait declaration. Includes defaulted items. - items: Vec>, + items: Vec, }, InherentImpl { param_env: ParamEnv, /// The type to which this block applies. ty: Ty, /// Associated items, in definition order. - items: Vec<(AssocItem, Arc>)>, + items: Vec, }, // Functions @@ -441,10 +442,7 @@ where items: tcx .associated_items(def_id) .in_definition_order() - .map(|assoc| { - let def_id = assoc.def_id.sinto(s); - (assoc.sinto(s), def_id.full_def(s)) - }) + .map(|assoc| assoc.sinto(s)) .collect::>(), }, RDefKind::TraitAlias { .. } => FullDefKind::TraitAlias { @@ -460,10 +458,7 @@ where let items = tcx .associated_items(def_id) .in_definition_order() - .map(|assoc| { - let def_id = assoc.def_id.sinto(s); - (assoc.sinto(s), def_id.full_def(s)) - }) + .map(|assoc| assoc.sinto(s)) .collect::>(); FullDefKind::InherentImpl { param_env, @@ -492,7 +487,6 @@ where .in_definition_order() .map(|decl_assoc| { let decl_def_id = decl_assoc.def_id; - let decl_def = decl_def_id.sinto(s).full_def(s); // Impl exprs required by the item. let required_impl_exprs; let value = match item_map.remove(&decl_def_id) { @@ -510,7 +504,7 @@ where }; ImplAssocItemValue::Provided { - def: impl_assoc.def_id.sinto(s).full_def(s), + def_id: impl_assoc.def_id.sinto(s), is_override: decl_assoc.defaultness(tcx).has_value(), } } @@ -554,7 +548,7 @@ where name: decl_assoc.opt_name().sinto(s), value, required_impl_exprs, - decl_def, + decl_def_id: decl_def_id.sinto(s), } }) .collect(); @@ -699,12 +693,12 @@ where /// that reuses the trait decl default value. #[derive_group(Serializers)] #[derive(Clone, Debug, JsonSchema)] -pub struct ImplAssocItem { +pub struct ImplAssocItem { /// This is `None` for RPTITs. pub name: Option, - /// The definition of the item from the trait declaration. This is `AssocTy`, `AssocFn` or + /// The definition of the item from the trait declaration. This is an `AssocTy`, `AssocFn` or /// `AssocConst`. - pub decl_def: Arc>, + pub decl_def_id: DefId, /// The `ImplExpr`s required to satisfy the predicates on the associated type. E.g.: /// ```ignore /// trait Foo { @@ -717,17 +711,17 @@ pub struct ImplAssocItem { /// Empty if this item is an associated const or fn. pub required_impl_exprs: Vec, /// The value of the implemented item. - pub value: ImplAssocItemValue, + pub value: ImplAssocItemValue, } #[derive_group(Serializers)] #[derive(Clone, Debug, JsonSchema)] -pub enum ImplAssocItemValue { +pub enum ImplAssocItemValue { /// The item is provided by the trait impl. Provided { - /// The definition of the item in the trait impl. This is `AssocTy`, `AssocFn` or + /// The definition of the item in the trait impl. This is an `AssocTy`, `AssocFn` or /// `AssocConst`. - def: Arc>, + def_id: DefId, /// Whether the trait had a default value for this item (which is therefore overriden). is_override: bool, }, @@ -808,11 +802,11 @@ impl FullDef { .collect(), FullDefKind::InherentImpl { items, .. } | FullDefKind::Trait { items, .. } => items .iter() - .filter_map(|(item, _)| Some((item.name.clone()?, item.def_id.clone()))) + .filter_map(|item| Some((item.name.clone()?, item.def_id.clone()))) .collect(), FullDefKind::TraitImpl { items, .. } => items .iter() - .filter_map(|item| Some((item.name.clone()?, item.def().def_id.clone()))) + .filter_map(|item| Some((item.name.clone()?, item.def_id().clone()))) .collect(), _ => vec![], }; @@ -831,29 +825,13 @@ impl FullDef { } } -impl ImplAssocItem { +impl ImplAssocItem { /// The relevant definition: the provided implementation if any, otherwise the default /// declaration from the trait declaration. - pub fn def(&self) -> &FullDef { + pub fn def_id(&self) -> &DefId { match &self.value { - ImplAssocItemValue::Provided { def, .. } => def.as_ref(), - _ => self.decl_def.as_ref(), - } - } - - /// The kind of item this is. - pub fn assoc_kind(&self) -> &AssocKind { - match self.def().kind() { - FullDefKind::AssocTy { - associated_item, .. - } - | FullDefKind::AssocFn { - associated_item, .. - } - | FullDefKind::AssocConst { - associated_item, .. - } => &associated_item.kind, - _ => unreachable!(), + ImplAssocItemValue::Provided { def_id, .. } => def_id, + _ => &self.decl_def_id, } } } From f98a7c81fff8e24df33b156c53bad87308df7cf4 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 11 Jul 2025 15:43:06 +0200 Subject: [PATCH 35/51] Implement `SInto` for `AssocItem` manually --- frontend/exporter/src/types/ty.rs | 85 ++++++++++++++++--------------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index 1907e792e..7041b0ab6 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -1652,24 +1652,62 @@ pub enum PredicateKind { } /// Reflects [`ty::AssocItem`] -#[derive(AdtInto)] -#[args(<'tcx, S: BaseState<'tcx>>, from: ty::AssocItem, state: S as s)] #[derive_group(Serializers)] #[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct AssocItem { pub def_id: DefId, /// This is `None` for RPTITs. - #[value(self.opt_name().sinto(s))] pub name: Option, pub kind: AssocKind, - #[value(get_container_for_assoc_item(s, self))] pub container: AssocItemContainer, /// Whether this item has a value (e.g. this is `false` for trait methods without default /// implementations). - #[value(self.defaultness(s.base().tcx).has_value())] pub has_value: bool, } +#[cfg(feature = "rustc")] +impl<'tcx, S: BaseState<'tcx>> SInto for ty::AssocItem { + fn sinto(&self, s: &S) -> AssocItem { + let tcx = s.base().tcx; + // We want to solve traits in the context of this item. + let state_with_id = &s.with_owner_id(self.def_id); + let container_id = self.container_id(tcx); + let container = match self.container { + ty::AssocItemContainer::Trait => { + let trait_ref = ty::TraitRef::identity(tcx, container_id).sinto(state_with_id); + AssocItemContainer::TraitContainer { trait_ref } + } + ty::AssocItemContainer::Impl => { + if let Some(implemented_trait_item) = self.trait_item_def_id { + let impl_generics = ty::GenericArgs::identity_for_item(tcx, container_id); + let item = translate_item_ref(state_with_id, container_id, impl_generics); + let implemented_trait_ref = tcx + .impl_trait_ref(container_id) + .unwrap() + .instantiate_identity(); + AssocItemContainer::TraitImplContainer { + impl_: item, + implemented_trait_ref: implemented_trait_ref.sinto(state_with_id), + implemented_trait_item: implemented_trait_item.sinto(s), + overrides_default: tcx.defaultness(implemented_trait_item).has_value(), + } + } else { + AssocItemContainer::InherentImplContainer { + impl_id: container_id.sinto(s), + } + } + } + }; + AssocItem { + def_id: self.def_id.sinto(s), + name: self.opt_name().sinto(s), + kind: self.kind.sinto(s), + container, + has_value: self.defaultness(tcx).has_value(), + } + } +} + /// Reflects [`ty::AssocKind`] #[derive(AdtInto)] #[args(<'tcx, S: BaseState<'tcx>>, from: ty::AssocKind, state: S as _tcx)] @@ -1713,43 +1751,6 @@ pub enum AssocItemContainer { }, } -#[cfg(feature = "rustc")] -fn get_container_for_assoc_item<'tcx, S: BaseState<'tcx>>( - s: &S, - item: &ty::AssocItem, -) -> AssocItemContainer { - let tcx = s.base().tcx; - // We want to solve traits in the context of this item. - let state_with_id = &s.with_owner_id(item.def_id); - let container_id = item.container_id(tcx); - match item.container { - ty::AssocItemContainer::Trait => { - let trait_ref = ty::TraitRef::identity(tcx, container_id).sinto(state_with_id); - AssocItemContainer::TraitContainer { trait_ref } - } - ty::AssocItemContainer::Impl => { - if let Some(implemented_trait_item) = item.trait_item_def_id { - let impl_generics = ty::GenericArgs::identity_for_item(tcx, container_id); - let item = translate_item_ref(state_with_id, container_id, impl_generics); - let implemented_trait_ref = tcx - .impl_trait_ref(container_id) - .unwrap() - .instantiate_identity(); - AssocItemContainer::TraitImplContainer { - impl_: item, - implemented_trait_ref: implemented_trait_ref.sinto(state_with_id), - implemented_trait_item: implemented_trait_item.sinto(s), - overrides_default: tcx.defaultness(implemented_trait_item).has_value(), - } - } else { - AssocItemContainer::InherentImplContainer { - impl_id: container_id.sinto(s), - } - } - } - } -} - /// Reflects [`ty::ImplTraitInTraitData`] #[derive(AdtInto)] #[args(<'tcx, S: BaseState<'tcx>>, from: ty::ImplTraitInTraitData, state: S as _s)] From 60d847f2336e21a6ac51cee0f061d8ae05dca1c5 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 10 Jul 2025 13:34:16 +0200 Subject: [PATCH 36/51] Allow recovering the `ty::GenericArgs` from an `ItemRef` --- frontend/exporter/src/id_table.rs | 6 +++++- frontend/exporter/src/state.rs | 4 +++- frontend/exporter/src/types/mir.rs | 4 ++-- frontend/exporter/src/types/ty.rs | 34 +++++++++++++++++++++++------- 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/frontend/exporter/src/id_table.rs b/frontend/exporter/src/id_table.rs index 3e2cb47ea..bf29e92c2 100644 --- a/frontend/exporter/src/id_table.rs +++ b/frontend/exporter/src/id_table.rs @@ -24,7 +24,7 @@ use std::{ /// Unique IDs in a ID table. #[derive_group(Serializers)] -#[derive(Default, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Default, Clone, Copy, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[serde(transparent)] pub struct Id { id: u32, @@ -209,6 +209,10 @@ impl> Node { pub fn inner(&self) -> &Arc { &self.value } + + pub fn id(&self) -> Id { + self.id + } } /// Wrapper for a type `T` that creates a bundle containing both a ID diff --git a/frontend/exporter/src/state.rs b/frontend/exporter/src/state.rs index 6258e0ad9..58791a496 100644 --- a/frontend/exporter/src/state.rs +++ b/frontend/exporter/src/state.rs @@ -88,6 +88,8 @@ mod types { pub per_item: HashMap>, /// A ID table session, providing fresh IDs. pub id_table_session: id_table::Session, + /// Map that recovers rustc args for a given `ItemRef`. + pub reverse_item_refs_map: HashMap>, } /// Defines a mapping from types to types, for use with `TypeMap`. @@ -113,7 +115,7 @@ mod types { pub promoteds: TypeMap, /// Cache the `Ty` translations. pub tys: HashMap, Ty>, - /// Cache the `ItemRef` translations. + /// Cache the `ItemRef` translations. This is fast because `GenericArgsRef` is interned. pub item_refs: HashMap<(RDefId, ty::GenericArgsRef<'tcx>), ItemRef>, /// Cache the trait resolution engine for each item. pub predicate_searcher: Option>, diff --git a/frontend/exporter/src/types/mir.rs b/frontend/exporter/src/types/mir.rs index b615e7de1..a5ab8738d 100644 --- a/frontend/exporter/src/types/mir.rs +++ b/frontend/exporter/src/types/mir.rs @@ -259,9 +259,9 @@ fn translate_mir_const<'tcx, S: UnderOwnerState<'tcx>>( match ucv.promoted { Some(promoted) => { let mut item = translate_item_ref(s, ucv.def, ucv.args); - item.mutate(s, |item| { + item.mutate_def_id(s, |def_id| { // Construct a def_id for the promoted constant. - item.def_id = item.def_id.make_promoted_child(s, promoted.sinto(s)); + *def_id = def_id.make_promoted_child(s, promoted.sinto(s)); }); Promoted(item) } diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index 7041b0ab6..3f899d3c7 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -557,6 +557,9 @@ impl ItemRef { s.with_cache(|cache| { cache.item_refs.insert(key, item.clone()); }); + s.with_global_cache(|cache| { + cache.reverse_item_refs_map.insert(item.id(), generics); + }); item } @@ -564,15 +567,30 @@ impl ItemRef { &self.contents } + /// Get a unique id identitying this `ItemRef`. + pub fn id(&self) -> id_table::Id { + self.contents.id() + } + + /// Recover the original rustc args that generated this `ItemRef`. Will panic if the `ItemRef` + /// was built by hand instead of using `translate_item_ref`. #[cfg(feature = "rustc")] - pub fn mutate<'tcx, S: BaseState<'tcx>>( - &mut self, - s: &S, - f: impl FnOnce(&mut ItemRefContents), - ) { - let mut contents = self.contents().clone(); - f(&mut contents); - *self = contents.intern(s); + pub fn rustc_args<'tcx, S: BaseState<'tcx>>(&self, s: &S) -> ty::GenericArgsRef<'tcx> { + s.with_global_cache(|cache| *cache.reverse_item_refs_map.get(&self.id()).unwrap()) + } + + /// Mutate the `DefId`, keeping the same generic args. + #[cfg(feature = "rustc")] + pub fn mutate_def_id<'tcx, S: BaseState<'tcx>>(&mut self, s: &S, f: impl FnOnce(&mut DefId)) { + let args = self.rustc_args(s); + { + let mut contents = self.contents().clone(); + f(&mut contents.def_id); + *self = contents.intern(s); + }; + s.with_global_cache(|cache| { + cache.reverse_item_refs_map.insert(self.id(), args); + }); } } From 7bfa4994d2fd77b526aef23b5f5f081bacec9413 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 11 Jul 2025 15:49:55 +0200 Subject: [PATCH 37/51] full_def: allow instantiating `FullDef` with generics --- frontend/exporter/src/body.rs | 44 +++- frontend/exporter/src/rustc_utils.rs | 63 ++++- frontend/exporter/src/traits.rs | 2 +- frontend/exporter/src/types/new/full_def.rs | 268 +++++++++++++++----- frontend/exporter/src/types/ty.rs | 85 ++++--- 5 files changed, 341 insertions(+), 121 deletions(-) diff --git a/frontend/exporter/src/body.rs b/frontend/exporter/src/body.rs index 57bba80d6..e1dd080ba 100644 --- a/frontend/exporter/src/body.rs +++ b/frontend/exporter/src/body.rs @@ -13,6 +13,7 @@ mod module { def_id::{DefId as RDefId, LocalDefId as RLocalDefId}, hir_id::OwnerId as ROwnerId, }; + use rustc_middle::ty; mod store { //! This module helps at store bodies to avoid stealing. @@ -122,7 +123,11 @@ mod module { } pub trait IsBody: Sized + std::fmt::Debug + Clone + 'static { - fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RDefId, s: &S) -> Option; + fn body<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + did: RDefId, + instantiate: Option>, + ) -> Option; /// Reuse a MIR body we already got. Panic if that's impossible. fn from_mir<'tcx, S: UnderOwnerState<'tcx>>( @@ -146,7 +151,7 @@ mod module { FnDef { params: thir.params.raw.sinto(s), ret: thir.exprs[expr_entrypoint].ty.sinto(s), - body: Body::body(ldid.to_def_id(), s).s_unwrap(s), + body: Body::body(s, ldid.to_def_id(), None).s_unwrap(s), sig_span: fn_sig.span.sinto(s), header: fn_sig.header.sinto(s), } @@ -161,13 +166,17 @@ mod module { // be local. It is safe to do so, because if we have access to HIR objects, // it necessarily means we are exploring a local item (we don't have // access to the HIR of external objects, only their MIR). - Body::body(s.base().tcx.hir_body_owner_def_id(id).to_def_id(), s).s_unwrap(s) + Body::body(s, s.base().tcx.hir_body_owner_def_id(id).to_def_id(), None).s_unwrap(s) } mod implementations { use super::*; impl IsBody for () { - fn body<'tcx, S: UnderOwnerState<'tcx>>(_did: RDefId, _s: &S) -> Option { + fn body<'tcx, S: UnderOwnerState<'tcx>>( + _s: &S, + _did: RDefId, + _instantiate: Option>, + ) -> Option { Some(()) } fn from_mir<'tcx, S: UnderOwnerState<'tcx>>( @@ -178,9 +187,14 @@ mod module { } } impl IsBody for ThirBody { - fn body<'tcx, S: BaseState<'tcx>>(did: RDefId, s: &S) -> Option { + fn body<'tcx, S: BaseState<'tcx>>( + s: &S, + did: RDefId, + instantiate: Option>, + ) -> Option { let did = did.as_local()?; let (thir, expr) = get_thir(did, s); + assert!(instantiate.is_none(), "monomorphized thir isn't supported"); let s = &s.with_owner_id(did.to_def_id()); Some(if *CORE_EXTRACTION_MODE { let expr = &thir.exprs[expr]; @@ -198,15 +212,25 @@ mod module { } impl IsBody for (A, B) { - fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RDefId, s: &S) -> Option { - Some((A::body(did, s)?, B::body(did, s)?)) + fn body<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + did: RDefId, + instantiate: Option>, + ) -> Option { + Some((A::body(s, did, instantiate)?, B::body(s, did, instantiate)?)) } } impl IsBody for MirBody { - fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RDefId, s: &S) -> Option { - MirKind::get_mir(s.base().tcx, did, |body| { - let body = Rc::new(body.clone()); + fn body<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + did: RDefId, + instantiate: Option>, + ) -> Option { + let tcx = s.base().tcx; + MirKind::get_mir(tcx, did, |body| { + let body = substitute(tcx, instantiate, body.clone()); + let body = Rc::new(body); body.sinto(&s.with_mir(body.clone())) }) } diff --git a/frontend/exporter/src/rustc_utils.rs b/frontend/exporter/src/rustc_utils.rs index cb6ae4c6a..c2cf36e39 100644 --- a/frontend/exporter/src/rustc_utils.rs +++ b/frontend/exporter/src/rustc_utils.rs @@ -2,6 +2,27 @@ use crate::prelude::*; use rustc_hir::def::DefKind as RDefKind; use rustc_middle::{mir, ty}; +pub fn inst_binder<'tcx, T>( + tcx: ty::TyCtxt<'tcx>, + args: Option>, + x: ty::EarlyBinder<'tcx, T>, +) -> T +where + T: ty::TypeFoldable>, +{ + match args { + None => x.instantiate_identity(), + Some(args) => x.instantiate(tcx, args), + } +} + +pub fn substitute<'tcx, T>(tcx: ty::TyCtxt<'tcx>, args: Option>, x: T) -> T +where + T: ty::TypeFoldable>, +{ + inst_binder(tcx, args, ty::EarlyBinder::bind(x)) +} + #[extension_traits::extension(pub trait SubstBinder)] impl<'tcx, T: ty::TypeFoldable>> ty::Binder<'tcx, T> { fn subst( @@ -240,8 +261,13 @@ pub fn get_foreign_mod_children<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> /// } /// } /// ``` -pub fn get_method_sig<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> ty::PolyFnSig<'tcx> { - let real_sig = tcx.fn_sig(def_id).instantiate_identity(); +pub fn get_method_sig<'tcx>( + tcx: ty::TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + def_id: RDefId, + method_args: Option>, +) -> ty::PolyFnSig<'tcx> { + let real_sig = inst_binder(tcx, typing_env, method_args, tcx.fn_sig(def_id)); let item = tcx.associated_item(def_id); if !matches!(item.container, ty::AssocItemContainer::Impl) { return real_sig; @@ -261,20 +287,21 @@ pub fn get_method_sig<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> ty::PolyFn } let impl_def_id = item.container_id(tcx); + let method_args = + method_args.unwrap_or_else(|| ty::GenericArgs::identity_for_item(tcx, def_id)); // The trait predicate that is implemented by the surrounding impl block. let implemented_trait_ref = tcx .impl_trait_ref(impl_def_id) .unwrap() - .instantiate_identity(); + .instantiate(tcx, method_args); // Construct arguments for the declared method generics in the context of the implemented // method generics. - let impl_args = ty::GenericArgs::identity_for_item(tcx, def_id); - let decl_args = impl_args.rebase_onto(tcx, impl_def_id, implemented_trait_ref.args); + let decl_args = method_args.rebase_onto(tcx, impl_def_id, implemented_trait_ref.args); let sig = declared_sig.instantiate(tcx, decl_args); // Avoids accidentally using the same lifetime name twice in the same scope // (once in impl parameters, second in the method declaration late-bound vars). let sig = tcx.anonymize_bound_vars(sig); - sig + normalize(tcx, typing_env, sig) } pub fn closure_once_shim<'tcx>( @@ -295,15 +322,25 @@ pub fn closure_once_shim<'tcx>( Some(mir) } -pub fn drop_glue_shim<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> Option> { +pub fn drop_glue_shim<'tcx>( + tcx: ty::TyCtxt<'tcx>, + def_id: RDefId, + instantiate: Option>, +) -> Option> { let drop_in_place = tcx.require_lang_item(rustc_hir::LangItem::DropInPlace, rustc_span::DUMMY_SP); - if !tcx.generics_of(def_id).is_empty() { - // Hack: layout code panics if it can't fully normalize types, which can happen e.g. with a - // trait associated type. For now we only translate the glue for monomorphic types. - return None; - } - let ty = tcx.type_of(def_id).instantiate_identity(); + let ty = tcx.type_of(def_id); + let ty = match instantiate { + None => { + if !tcx.generics_of(def_id).is_empty() { + // Hack: layout code panics if it can't fully normalize types, which can happen e.g. with a + // trait associated type. For now we only translate the glue for monomorphic types. + return None; + } + ty.instantiate_identity() + } + Some(args) => ty.instantiate(tcx, args), + }; let instance_kind = ty::InstanceKind::DropGlue(drop_in_place, Some(ty)); let mir = tcx.instance_mir(instance_kind).clone(); Some(mir) diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index cb079454e..b6c83803a 100644 --- a/frontend/exporter/src/traits.rs +++ b/frontend/exporter/src/traits.rs @@ -57,7 +57,7 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for resolution: .. } => ImplExprPathChunk::AssocItem { item: translate_item_ref(s, item.def_id, generic_args), - assoc_item: item.sinto(s), + assoc_item: AssocItem::sfrom(s, item), predicate: predicate.sinto(s), predicate_id: <_ as SInto<_, Clause>>::sinto(predicate, s).id, index: index.sinto(s), diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 37c973342..5ed66b5aa 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -36,7 +36,13 @@ pub struct FullDef { } #[cfg(feature = "rustc")] -fn translate_full_def<'tcx, S, Body>(s: &S, def_id: &DefId) -> FullDef +/// Construct the `FullDefKind` for this item. If `args` is `Some`, the returned `FullDef` will be +/// instantiated with the provided generics. +fn translate_full_def<'tcx, S, Body>( + s: &S, + def_id: &DefId, + args: Option>, +) -> FullDef where S: BaseState<'tcx>, Body: IsBody + TypeMappable, @@ -52,7 +58,7 @@ where let kind; match def_id.promoted_id() { None => { - kind = translate_full_def_kind(s, rust_def_id); + kind = translate_full_def_kind(s, rust_def_id, args); let def_kind = get_def_kind(tcx, rust_def_id); source_span = rust_def_id.as_local().map(|ldid| tcx.source_span(ldid)); @@ -68,7 +74,11 @@ where } Some(promoted_id) => { - let parent_def = def_id.parent.as_ref().unwrap().full_def::<_, Body>(s); + let parent_def = def_id + .parent + .as_ref() + .unwrap() + .full_def_maybe_instantiated::<_, Body>(s, args); let parent_param_env = parent_def.param_env().unwrap(); let param_env = ParamEnv { generics: TyGenerics { @@ -81,6 +91,7 @@ where predicates: GenericPredicates { predicates: vec![] }, }; let body = get_promoted_mir(tcx, rust_def_id, promoted_id.as_rust_promoted_id()); + let body = substitute(tcx, s.typing_env(), args, body); source_span = Some(body.span); let ty: Ty = body.local_decls[rustc_middle::mir::Local::ZERO] @@ -144,7 +155,7 @@ impl DefId { }) { return def; } - let def = Arc::new(translate_full_def(s, self)); + let def = Arc::new(translate_full_def(s, self, None)); s.with_item_cache(rust_def_id, |cache| match self.promoted_id() { None => { cache.full_def.insert(def.clone()); @@ -158,6 +169,38 @@ impl DefId { }); def } + + /// Get the full definition of this item, instantiated if `args` is `Some`. + pub fn full_def_maybe_instantiated<'tcx, S, Body>( + &self, + s: &S, + instantiate: Option>, + ) -> Arc> + where + Body: IsBody + TypeMappable, + S: BaseState<'tcx>, + { + match instantiate { + None => self.full_def(s), + Some(args) => { + // TODO: cache + Arc::new(translate_full_def(s, self, Some(args))) + } + } + } +} + +#[cfg(feature = "rustc")] +impl ItemRef { + /// Get the full definition of the item, instantiated with the provided generics. + pub fn instantiated_full_def<'tcx, S, Body>(&self, s: &S) -> Arc> + where + Body: IsBody + TypeMappable, + S: BaseState<'tcx>, + { + let args = self.rustc_args(s); + self.def_id.full_def_maybe_instantiated(s, Some(args)) + } } /// The combination of type generics and related predicates. @@ -367,13 +410,26 @@ pub enum FullDefKind { } #[cfg(feature = "rustc")] -fn translate_full_def_kind<'tcx, S, Body>(s: &S, def_id: RDefId) -> FullDefKind +/// Construct the `FullDefKind` for this item. +/// +/// If `args` is `Some`, instantiate the whole definition with these generics; otherwise keep the +/// polymorphic definition. +// Note: this is tricky to get right, we have to make sure to isntantiate every single field that +// may contain a type/const/trait reference. +fn translate_full_def_kind<'tcx, S, Body>( + s: &S, + def_id: RDefId, + args: Option>, +) -> FullDefKind where S: BaseState<'tcx>, Body: IsBody + TypeMappable, { let s = &s.with_owner_id(def_id); let tcx = s.base().tcx; + let type_of_self = || inst_binder(tcx, args, tcx.type_of(def_id)); + let args_or_default = + || args.unwrap_or_else(|| ty::GenericArgs::identity_for_item(tcx, def_id)); match get_def_kind(tcx, def_id) { RDefKind::Struct { .. } | RDefKind::Union { .. } | RDefKind::Enum { .. } => { let def = tcx.adt_def(def_id); @@ -391,25 +447,21 @@ where ty: tcx.types.isize, } }; - VariantDef::sfrom(s, variant, discr) + VariantDef::sfrom(s, variant, discr, args) }) .collect(); let drop_trait = tcx.lang_items().drop_trait().unwrap(); FullDefKind::Adt { - param_env: get_param_env(s), + param_env: get_param_env(s, args), adt_kind: def.adt_kind().sinto(s), variants, flags: def.flags().sinto(s), repr: def.repr().sinto(s), - drop_glue: get_drop_glue_shim(s), + drop_glue: get_drop_glue_shim(s, args), drop_impl: virtual_impl_for( s, - ty::TraitRef::new( - tcx, - drop_trait, - [tcx.type_of(def_id).instantiate_identity()], - ), + ty::TraitRef::new(tcx, drop_trait, [type_of_self()]), ), } } @@ -419,46 +471,62 @@ where ..s.base() }); FullDefKind::TyAlias { - param_env: get_param_env(s), - ty: tcx.type_of(def_id).instantiate_identity().sinto(s), + param_env: get_param_env(s, args), + ty: type_of_self().sinto(s), } } RDefKind::ForeignTy => FullDefKind::ForeignTy, RDefKind::AssocTy { .. } => FullDefKind::AssocTy { - param_env: get_param_env(s), - implied_predicates: get_implied_predicates(s), - associated_item: tcx.associated_item(def_id).sinto(s), + param_env: get_param_env(s, args), + implied_predicates: get_implied_predicates(s, args), + associated_item: AssocItem::sfrom_instantiated(s, &tcx.associated_item(def_id), args), value: if tcx.defaultness(def_id).has_value() { - Some(tcx.type_of(def_id).instantiate_identity().sinto(s)) + Some(type_of_self().sinto(s)) } else { None }, }, RDefKind::OpaqueTy => FullDefKind::OpaqueTy, RDefKind::Trait { .. } => FullDefKind::Trait { - param_env: get_param_env(s), - implied_predicates: get_implied_predicates(s), - self_predicate: get_self_predicate(s), + param_env: get_param_env(s, args), + implied_predicates: get_implied_predicates(s, args), + self_predicate: get_self_predicate(s, args), items: tcx .associated_items(def_id) .in_definition_order() - .map(|assoc| assoc.sinto(s)) + .map(|assoc| { + let item_args = args.map(|args| { + let item_identity_args = + ty::GenericArgs::identity_for_item(tcx, assoc.def_id); + let item_args = item_identity_args.rebase_onto(tcx, def_id, args); + tcx.mk_args(item_args) + }); + AssocItem::sfrom_instantiated(s, assoc, item_args) + }) .collect::>(), }, RDefKind::TraitAlias { .. } => FullDefKind::TraitAlias { - param_env: get_param_env(s), - implied_predicates: get_implied_predicates(s), - self_predicate: get_self_predicate(s), + param_env: get_param_env(s, args), + implied_predicates: get_implied_predicates(s, args), + self_predicate: get_self_predicate(s, args), }, RDefKind::Impl { .. } => { use std::collections::HashMap; - let param_env = get_param_env(s); - match tcx.impl_subject(def_id).instantiate_identity() { + let param_env = get_param_env(s, args); + match inst_binder(tcx, args, tcx.impl_subject(def_id)) { ty::ImplSubject::Inherent(ty) => { let items = tcx .associated_items(def_id) .in_definition_order() - .map(|assoc| assoc.sinto(s)) + .map(|assoc| { + let item_args = args.map(|args| { + let item_identity_args = + ty::GenericArgs::identity_for_item(tcx, assoc.def_id); + let item_args = item_identity_args.rebase_onto(tcx, def_id, args); + tcx.mk_args(item_args) + }); + AssocItem::sfrom_instantiated(s, assoc, item_args) + }) .collect::>(); FullDefKind::InherentImpl { param_env, @@ -563,27 +631,27 @@ where } } RDefKind::Fn { .. } => FullDefKind::Fn { - param_env: get_param_env(s), + param_env: get_param_env(s, args), inline: tcx.codegen_fn_attrs(def_id).inline.sinto(s), is_const: tcx.constness(def_id) == rustc_hir::Constness::Const, - sig: tcx.fn_sig(def_id).instantiate_identity().sinto(s), - body: Body::body(def_id, s), + sig: inst_binder(tcx, args, tcx.fn_sig(def_id)).sinto(s), + body: get_body(s, args), }, RDefKind::AssocFn { .. } => FullDefKind::AssocFn { - param_env: get_param_env(s), - associated_item: tcx.associated_item(def_id).sinto(s), + param_env: get_param_env(s, args), + associated_item: AssocItem::sfrom_instantiated(s, &tcx.associated_item(def_id), args), inline: tcx.codegen_fn_attrs(def_id).inline.sinto(s), is_const: tcx.constness(def_id) == rustc_hir::Constness::Const, - sig: get_method_sig(tcx, def_id).sinto(s), - body: Body::body(def_id, s), + sig: get_method_sig(tcx, s.typing_env(), def_id, args).sinto(s), + body: get_body(s, args), }, RDefKind::Closure { .. } => { use ty::ClosureKind::{Fn, FnMut}; - let closure_ty = tcx.type_of(def_id).instantiate_identity(); - let ty::TyKind::Closure(_, args) = closure_ty.kind() else { + let closure_ty = type_of_self(); + let ty::TyKind::Closure(_, closure_args) = closure_ty.kind() else { unreachable!() }; - let closure = args.as_closure(); + let closure = closure_args.as_closure(); // We lose lifetime information here. Eventually would be nice not to. let input_ty = erase_free_regions(tcx, closure.sig().input(0).skip_binder()); let trait_args = [closure_ty, input_ty]; @@ -595,14 +663,10 @@ where is_const: tcx.constness(def_id) == rustc_hir::Constness::Const, args: ClosureArgs::sfrom(s, def_id, closure), once_shim: get_closure_once_shim(s, closure_ty), - drop_glue: get_drop_glue_shim(s), + drop_glue: get_drop_glue_shim(s, args), drop_impl: virtual_impl_for( s, - ty::TraitRef::new( - tcx, - drop_trait, - [tcx.type_of(def_id).instantiate_identity()], - ), + ty::TraitRef::new(tcx, drop_trait, [type_of_self()]), ), fn_once_impl: virtual_impl_for( s, @@ -624,17 +688,17 @@ where _ => unreachable!(), }; FullDefKind::Const { - param_env: get_param_env(s), - ty: tcx.type_of(def_id).instantiate_identity().sinto(s), + param_env: get_param_env(s, args), + ty: type_of_self().sinto(s), kind, - body: Body::body(def_id, s), + body: get_body(s, args), } } RDefKind::AssocConst { .. } => FullDefKind::AssocConst { - param_env: get_param_env(s), - associated_item: tcx.associated_item(def_id).sinto(s), - ty: tcx.type_of(def_id).instantiate_identity().sinto(s), - body: Body::body(def_id, s), + param_env: get_param_env(s, args), + associated_item: AssocItem::sfrom_instantiated(s, &tcx.associated_item(def_id), args), + ty: type_of_self().sinto(s), + body: get_body(s, args), }, RDefKind::Static { safety, @@ -642,12 +706,12 @@ where nested, .. } => FullDefKind::Static { - param_env: get_param_env(s), + param_env: get_param_env(s, args), safety: safety.sinto(s), mutability: mutability.sinto(s), nested: nested.sinto(s), - ty: tcx.type_of(def_id).instantiate_identity().sinto(s), - body: Body::body(def_id, s), + ty: type_of_self().sinto(s), + body: get_body(s, args), }, RDefKind::ExternCrate => FullDefKind::ExternCrate, RDefKind::Use => FullDefKind::Use, @@ -662,6 +726,7 @@ where RDefKind::LifetimeParam => FullDefKind::LifetimeParam, RDefKind::Variant => FullDefKind::Variant, RDefKind::Ctor(ctor_of, _) => { + let args = args_or_default(); let ctor_of = ctor_of.sinto(s); // The def_id of the adt this ctor belongs to. @@ -671,9 +736,13 @@ where }; let adt_def = tcx.adt_def(adt_def_id); let variant_id = adt_def.variant_index_with_ctor_id(def_id); - let fields = adt_def.variant(variant_id).fields.sinto(s); - let generic_args = ty::GenericArgs::identity_for_item(tcx, adt_def_id); - let output_ty = ty::Ty::new_adt(tcx, adt_def, generic_args).sinto(s); + let fields = adt_def + .variant(variant_id) + .fields + .iter() + .map(|f| FieldDef::sfrom(s, f, args)) + .collect(); + let output_ty = ty::Ty::new_adt(tcx, adt_def, args).sinto(s); FullDefKind::Ctor { adt_def_id: adt_def_id.sinto(s), ctor_of, @@ -781,6 +850,22 @@ impl FullDef { } } + /// Whether the item has any generics at all (including parent generics). + pub fn has_any_generics(&self) -> bool { + match self.param_env() { + Some(p) => p.generics.parent_count != 0 || !p.generics.params.is_empty(), + None => false, + } + } + + /// Whether the item has any generics of its own (ignoring parent generics). + pub fn has_own_generics(&self) -> bool { + match self.param_env() { + Some(p) => !p.generics.params.is_empty(), + None => false, + } + } + /// Lists the children of this item that can be named, in the way of normal rust paths. For /// types, this includes inherent items. #[cfg(feature = "rustc")] @@ -837,13 +922,17 @@ impl ImplAssocItem { } #[cfg(feature = "rustc")] -fn get_self_predicate<'tcx, S: UnderOwnerState<'tcx>>(s: &S) -> TraitPredicate { +fn get_self_predicate<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + args: Option>, +) -> TraitPredicate { use ty::Upcast; let tcx = s.base().tcx; let pred: ty::TraitPredicate = crate::traits::self_predicate(tcx, s.owner_id()) .no_bound_vars() .unwrap() .upcast(tcx); + let pred = substitute(tcx, args, pred); pred.sinto(s) } @@ -881,6 +970,16 @@ where }) } +#[cfg(feature = "rustc")] +fn get_body<'tcx, S, Body>(s: &S, args: Option>) -> Option +where + S: UnderOwnerState<'tcx>, + Body: IsBody + TypeMappable, +{ + let def_id = s.owner_id(); + Body::body(s, def_id, args) +} + #[cfg(feature = "rustc")] fn get_closure_once_shim<'tcx, S, Body>(s: &S, closure_ty: ty::Ty<'tcx>) -> Option where @@ -894,30 +993,65 @@ where } #[cfg(feature = "rustc")] -fn get_drop_glue_shim<'tcx, S, Body>(s: &S) -> Option +fn get_drop_glue_shim<'tcx, S, Body>(s: &S, args: Option>) -> Option where S: UnderOwnerState<'tcx>, Body: IsBody + TypeMappable, { let tcx = s.base().tcx; - let mir = crate::drop_glue_shim(tcx, s.owner_id())?; + let mir = crate::drop_glue_shim(tcx, s.owner_id(), args)?; let body = Body::from_mir(s, mir)?; Some(body) } #[cfg(feature = "rustc")] -fn get_param_env<'tcx, S: UnderOwnerState<'tcx>>(s: &S) -> ParamEnv { +fn get_param_env<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + args: Option>, +) -> ParamEnv { let tcx = s.base().tcx; let def_id = s.owner_id(); - ParamEnv { - generics: tcx.generics_of(def_id).sinto(s), - predicates: required_predicates(tcx, def_id, s.base().options.resolve_drop_bounds).sinto(s), + let generics = tcx.generics_of(def_id).sinto(s); + match args { + None => ParamEnv { + generics, + predicates: required_predicates(tcx, def_id, s.base().options.resolve_drop_bounds) + .sinto(s), + }, + // An instantiated item is monomorphic. + Some(_) => ParamEnv { + generics: TyGenerics { + parent_count: 0, + params: Default::default(), + ..generics + }, + predicates: GenericPredicates::default(), + }, } } #[cfg(feature = "rustc")] -fn get_implied_predicates<'tcx, S: UnderOwnerState<'tcx>>(s: &S) -> GenericPredicates { +fn get_implied_predicates<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + args: Option>, +) -> GenericPredicates { + use std::borrow::Cow; let tcx = s.base().tcx; let def_id = s.owner_id(); - implied_predicates(tcx, def_id, s.base().options.resolve_drop_bounds).sinto(s) + let typing_env = s.typing_env(); + let mut implied_predicates = + implied_predicates(tcx, def_id, s.base().options.resolve_drop_bounds); + if args.is_some() { + implied_predicates = Cow::Owned( + implied_predicates + .iter() + .copied() + .map(|(clause, span)| { + let clause = substitute(tcx, typing_env, args, clause); + (clause, span) + }) + .collect(), + ); + } + implied_predicates.sinto(s) } diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index 3f899d3c7..4a1f650af 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -305,15 +305,16 @@ pub struct FieldDef { } #[cfg(feature = "rustc")] -impl<'tcx, S: UnderOwnerState<'tcx>> SInto for ty::FieldDef { - fn sinto(&self, s: &S) -> FieldDef { +impl FieldDef { + pub fn sfrom<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + fdef: &ty::FieldDef, + instantiate: ty::GenericArgsRef<'tcx>, + ) -> FieldDef { let tcx = s.base().tcx; - let ty = { - let generics = ty::GenericArgs::identity_for_item(tcx, self.did); - self.ty(tcx, generics).sinto(s) - }; + let ty = fdef.ty(tcx, instantiate).sinto(s); let name = { - let name = self.name.sinto(s); + let name = fdef.name.sinto(s); let is_user_provided = { // SH: Note that the only way I found of checking if the user wrote the name or if it // is just an integer generated by rustc is by checking if it is just made of @@ -324,11 +325,11 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for ty::FieldDef { }; FieldDef { - did: self.did.sinto(s), + did: fdef.did.sinto(s), name, - vis: self.vis.sinto(s), + vis: fdef.vis.sinto(s), ty, - span: tcx.def_span(self.did).sinto(s), + span: tcx.def_span(fdef.did).sinto(s), } } } @@ -356,14 +357,22 @@ impl VariantDef { s: &S, def: &ty::VariantDef, discr_val: ty::util::Discr<'tcx>, + instantiate: Option>, ) -> Self { + let tcx = s.base().tcx; + let instantiate = + instantiate.unwrap_or_else(|| ty::GenericArgs::identity_for_item(tcx, def.def_id)); VariantDef { def_id: def.def_id.sinto(s), ctor: def.ctor.sinto(s), name: def.name.sinto(s), discr_def: def.discr.sinto(s), discr_val: discr_val.sinto(s), - fields: def.fields.sinto(s), + fields: def + .fields + .iter() + .map(|f| FieldDef::sfrom(s, f, instantiate)) + .collect(), span: s.base().tcx.def_span(def.def_id).sinto(s), } } @@ -916,8 +925,9 @@ impl Alias { // is therefore difficult. Since our trait resolution ignores lifetimes anyway, we // just erase them. See also https://github.com/hacspec/hax/issues/747. let trait_ref = crate::traits::erase_free_regions(tcx, trait_ref); + let item = tcx.associated_item(alias_ty.def_id); AliasKind::Projection { - assoc_item: tcx.associated_item(alias_ty.def_id).sinto(s), + assoc_item: AssocItem::sfrom(s, &item), impl_expr: solve_trait(s, ty::Binder::dummy(trait_ref)), } } @@ -1138,9 +1148,10 @@ fn make_dyn<'tcx, S: UnderOwnerState<'tcx>>( let Term::Ty(ty) = proj.skip_binder().term.sinto(s) else { unreachable!() }; + let item = tcx.associated_item(alias_ty.def_id); ProjectionPredicate { impl_expr, - assoc_item: tcx.associated_item(alias_ty.def_id).sinto(s), + assoc_item: AssocItem::sfrom(s, &item), ty, } }; @@ -1408,9 +1419,10 @@ impl<'tcx, S: UnderBinderState<'tcx>> SInto let Term::Ty(ty) = self.term.sinto(s) else { unreachable!() }; + let item = tcx.associated_item(alias_ty.def_id); ProjectionPredicate { impl_expr: solve_trait(s, poly_trait_ref), - assoc_item: tcx.associated_item(alias_ty.def_id).sinto(s), + assoc_item: AssocItem::sfrom(s, &item), ty, } } @@ -1533,7 +1545,7 @@ impl Binder { #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::GenericPredicates<'tcx>, state: S as s)] #[derive_group(Serializers)] -#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Debug, Default, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct GenericPredicates { #[value(self.predicates.iter().map(|x| x.sinto(s)).collect())] pub predicates: Vec<(Clause, Span)>, @@ -1684,28 +1696,41 @@ pub struct AssocItem { } #[cfg(feature = "rustc")] -impl<'tcx, S: BaseState<'tcx>> SInto for ty::AssocItem { - fn sinto(&self, s: &S) -> AssocItem { +impl AssocItem { + pub fn sfrom<'tcx, S: BaseState<'tcx>>(s: &S, item: &ty::AssocItem) -> AssocItem { + Self::sfrom_instantiated(s, item, None) + } + + /// Translate an `AssocItem` and optionally instantiate it with the provided arguments. + pub fn sfrom_instantiated<'tcx, S: BaseState<'tcx>>( + s: &S, + item: &ty::AssocItem, + args: Option>, + ) -> AssocItem { let tcx = s.base().tcx; // We want to solve traits in the context of this item. - let state_with_id = &s.with_owner_id(self.def_id); - let container_id = self.container_id(tcx); - let container = match self.container { + let s = &s.with_owner_id(item.def_id); + let container_id = item.container_id(tcx); + let container_args = match args { + None => ty::GenericArgs::identity_for_item(tcx, container_id), + Some(args) => args.truncate_to(tcx, tcx.generics_of(container_id)), + }; + let container = match item.container { ty::AssocItemContainer::Trait => { - let trait_ref = ty::TraitRef::identity(tcx, container_id).sinto(state_with_id); + let trait_ref = + ty::TraitRef::new_from_args(tcx, container_id, container_args).sinto(s); AssocItemContainer::TraitContainer { trait_ref } } ty::AssocItemContainer::Impl => { - if let Some(implemented_trait_item) = self.trait_item_def_id { - let impl_generics = ty::GenericArgs::identity_for_item(tcx, container_id); - let item = translate_item_ref(state_with_id, container_id, impl_generics); + if let Some(implemented_trait_item) = item.trait_item_def_id { + let item = translate_item_ref(s, container_id, container_args); let implemented_trait_ref = tcx .impl_trait_ref(container_id) .unwrap() - .instantiate_identity(); + .instantiate(tcx, container_args); AssocItemContainer::TraitImplContainer { impl_: item, - implemented_trait_ref: implemented_trait_ref.sinto(state_with_id), + implemented_trait_ref: implemented_trait_ref.sinto(s), implemented_trait_item: implemented_trait_item.sinto(s), overrides_default: tcx.defaultness(implemented_trait_item).has_value(), } @@ -1717,11 +1742,11 @@ impl<'tcx, S: BaseState<'tcx>> SInto for ty::AssocItem { } }; AssocItem { - def_id: self.def_id.sinto(s), - name: self.opt_name().sinto(s), - kind: self.kind.sinto(s), + def_id: item.def_id.sinto(s), + name: item.opt_name().sinto(s), + kind: item.kind.sinto(s), container, - has_value: self.defaultness(tcx).has_value(), + has_value: item.defaultness(tcx).has_value(), } } } From 040d9a950584850b67ae4a8f5c5ea331e54acc23 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 18 Jul 2025 12:49:51 +0200 Subject: [PATCH 38/51] full_def: store a self-reference in `FullDef` --- frontend/exporter/src/rustc_utils.rs | 10 +++++ frontend/exporter/src/types/mir.rs | 4 +- frontend/exporter/src/types/new/full_def.rs | 31 +++++++++++---- frontend/exporter/src/types/ty.rs | 42 +++++++++++++++++---- 4 files changed, 71 insertions(+), 16 deletions(-) diff --git a/frontend/exporter/src/rustc_utils.rs b/frontend/exporter/src/rustc_utils.rs index c2cf36e39..2f8ef3d5c 100644 --- a/frontend/exporter/src/rustc_utils.rs +++ b/frontend/exporter/src/rustc_utils.rs @@ -34,6 +34,16 @@ impl<'tcx, T: ty::TypeFoldable>> ty::Binder<'tcx, T> { } } +/// Whether the item can have generic parameters. +pub(crate) fn can_have_generics<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> bool { + use RDefKind::*; + match get_def_kind(tcx, def_id) { + Mod | ConstParam | TyParam | LifetimeParam | Macro(..) | ExternCrate | Use | ForeignMod + | GlobalAsm => false, + _ => true, + } +} + #[tracing::instrument(skip(s))] pub(crate) fn get_variant_information<'s, S: UnderOwnerState<'s>>( adt_def: &ty::AdtDef<'s>, diff --git a/frontend/exporter/src/types/mir.rs b/frontend/exporter/src/types/mir.rs index a5ab8738d..29400f420 100644 --- a/frontend/exporter/src/types/mir.rs +++ b/frontend/exporter/src/types/mir.rs @@ -258,8 +258,8 @@ fn translate_mir_const<'tcx, S: UnderOwnerState<'tcx>>( ); match ucv.promoted { Some(promoted) => { - let mut item = translate_item_ref(s, ucv.def, ucv.args); - item.mutate_def_id(s, |def_id| { + let item = translate_item_ref(s, ucv.def, ucv.args); + let item = item.mutate_def_id(s, |def_id| { // Construct a def_id for the promoted constant. *def_id = def_id.make_promoted_child(s, promoted.sinto(s)); }); diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 5ed66b5aa..0938e8199 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -17,7 +17,9 @@ type DefaultFullDefBody = MirBody; #[derive_group(Serializers)] #[derive(Clone, Debug, JsonSchema)] pub struct FullDef { - pub def_id: DefId, + /// A reference to the current item. If the item was provided with generic args, they are + /// stored here; otherwise the args are the identity_args for this item. + pub this: ItemRef, /// The span of the definition of this item (e.g. for a function this is is signature). pub span: Span, /// The span of the whole definition (including e.g. the function body). @@ -49,7 +51,7 @@ where { let tcx = s.base().tcx; let rust_def_id = def_id.underlying_rust_def_id(); - let state_with_id = s.with_owner_id(rust_def_id); + let state_with_id = &s.with_owner_id(rust_def_id); let source_span; let attributes; let visibility; @@ -96,12 +98,12 @@ where let ty: Ty = body.local_decls[rustc_middle::mir::Local::ZERO] .ty - .sinto(&state_with_id); + .sinto(state_with_id); kind = FullDefKind::Const { param_env, ty, kind: ConstKind::PromotedConst, - body: Body::from_mir(&state_with_id, body), + body: Body::from_mir(state_with_id, body), }; // None of these make sense for a promoted constant. @@ -115,8 +117,18 @@ where let source_text = source_span .filter(|source_span| source_span.ctxt().is_root()) .and_then(|source_span| tcx.sess.source_map().span_to_snippet(source_span).ok()); + let this = if can_have_generics(tcx, rust_def_id) { + let args_or_default = + args.unwrap_or_else(|| ty::GenericArgs::identity_for_item(tcx, rust_def_id)); + let item = translate_item_ref(state_with_id, rust_def_id, args_or_default); + // Tricky: hax's DefId has more info (could be a promoted const), we must be careful to use + // the input DefId instead of the one derived from `rust_def_id`. + item.with_def_id(s, def_id) + } else { + ItemRef::dummy_without_generics(s, def_id.clone()) + }; FullDef { - def_id: def_id.clone(), + this, span: def_id.def_span(s), source_span: source_span.sinto(s), source_text, @@ -823,7 +835,12 @@ pub struct VirtualTraitImpl { impl FullDef { pub fn def_id(&self) -> &DefId { - &self.def_id + &self.this.def_id + } + + /// Reference to the item itself. + pub fn this(&self) -> &ItemRef { + &self.this } pub fn kind(&self) -> &FullDefKind { @@ -896,7 +913,7 @@ impl FullDef { _ => vec![], }; // Add inherent impl items if any. - if let Some(rust_def_id) = self.def_id.as_rust_def_id() { + if let Some(rust_def_id) = self.def_id().as_rust_def_id() { let tcx = s.base().tcx; for impl_def_id in tcx.inherent_impls(rust_def_id) { children.extend( diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index 4a1f650af..fad52eb56 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -514,6 +514,7 @@ impl ItemRefContents { } impl ItemRef { + /// The main way to obtain an `ItemRef`: from a `def_id` and generics. #[cfg(feature = "rustc")] pub fn translate<'tcx, S: UnderOwnerState<'tcx>>( s: &S, @@ -572,6 +573,24 @@ impl ItemRef { item } + /// Construct an `ItemRef` for items that can't have generics (e.g. modules). + #[cfg(feature = "rustc")] + pub fn dummy_without_generics<'tcx, S: BaseState<'tcx>>(s: &S, def_id: DefId) -> ItemRef { + let content = ItemRefContents { + def_id, + generic_args: Default::default(), + impl_exprs: Default::default(), + in_trait: Default::default(), + }; + let item = content.intern(s); + s.with_global_cache(|cache| { + cache + .reverse_item_refs_map + .insert(item.id(), ty::GenericArgsRef::default()); + }); + item + } + pub fn contents(&self) -> &ItemRefContents { &self.contents } @@ -590,16 +609,25 @@ impl ItemRef { /// Mutate the `DefId`, keeping the same generic args. #[cfg(feature = "rustc")] - pub fn mutate_def_id<'tcx, S: BaseState<'tcx>>(&mut self, s: &S, f: impl FnOnce(&mut DefId)) { + pub fn mutate_def_id<'tcx, S: BaseState<'tcx>>( + &self, + s: &S, + f: impl FnOnce(&mut DefId), + ) -> Self { let args = self.rustc_args(s); - { - let mut contents = self.contents().clone(); - f(&mut contents.def_id); - *self = contents.intern(s); - }; + let mut contents = self.contents().clone(); + f(&mut contents.def_id); + let new = contents.intern(s); s.with_global_cache(|cache| { - cache.reverse_item_refs_map.insert(self.id(), args); + cache.reverse_item_refs_map.insert(new.id(), args); }); + new + } + + /// Set the `DefId`, keeping the same generic args. + #[cfg(feature = "rustc")] + pub fn with_def_id<'tcx, S: BaseState<'tcx>>(&self, s: &S, def_id: &DefId) -> Self { + self.mutate_def_id(s, |d| *d = def_id.clone()) } } From 7d1c872f945d36270baf537c49d8e0e70ab0563e Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 19 Jul 2025 23:16:40 +0200 Subject: [PATCH 39/51] full_def: track parent item with appropriate args --- frontend/exporter/src/types/new/full_def.rs | 35 ++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 0938e8199..567734a7c 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -91,6 +91,7 @@ where has_late_bound_regions: None, }, predicates: GenericPredicates { predicates: vec![] }, + parent: Some(parent_def.this().clone()), }; let body = get_promoted_mir(tcx, rust_def_id, promoted_id.as_rust_promoted_id()); let body = substitute(tcx, s.typing_env(), args, body); @@ -223,6 +224,8 @@ pub struct ParamEnv { pub generics: TyGenerics, /// Required predicates for the item (see `traits::utils::required_predicates`). pub predicates: GenericPredicates, + /// A reference to the parent of this item, with appropriate args. + pub parent: Option, } /// The kind of a constant item. @@ -850,7 +853,7 @@ impl FullDef { /// Returns the generics and predicates for definitions that have those. pub fn param_env(&self) -> Option<&ParamEnv> { use FullDefKind::*; - match &self.kind { + match self.kind() { Adt { param_env, .. } | Trait { param_env, .. } | TraitAlias { param_env, .. } @@ -867,6 +870,27 @@ impl FullDef { } } + /// Return the parent of this item if the item inherits the typing context from its parent. + #[cfg(feature = "rustc")] + pub fn typing_parent<'tcx>(&self, s: &impl BaseState<'tcx>) -> Option { + use FullDefKind::*; + match self.kind() { + AssocTy { .. } + | AssocFn { .. } + | AssocConst { .. } + | Const { + kind: ConstKind::AnonConst | ConstKind::InlineConst | ConstKind::PromotedConst, + .. + } => self.param_env().unwrap().parent.clone(), + Closure { .. } | Ctor { .. } | Variant { .. } => { + let parent = self.def_id().parent.as_ref().unwrap(); + // The parent has the same generics as this item. + Some(self.this().with_def_id(s, parent)) + } + _ => None, + } + } + /// Whether the item has any generics at all (including parent generics). pub fn has_any_generics(&self) -> bool { match self.param_env() { @@ -1029,11 +1053,19 @@ fn get_param_env<'tcx, S: UnderOwnerState<'tcx>>( let tcx = s.base().tcx; let def_id = s.owner_id(); let generics = tcx.generics_of(def_id).sinto(s); + + let parent = generics.parent.as_ref().map(|parent| { + let parent = parent.underlying_rust_def_id(); + let args = args.unwrap_or_else(|| ty::GenericArgs::identity_for_item(tcx, def_id)); + let parent_args = args.truncate_to(tcx, tcx.generics_of(parent)); + translate_item_ref(s, parent, parent_args) + }); match args { None => ParamEnv { generics, predicates: required_predicates(tcx, def_id, s.base().options.resolve_drop_bounds) .sinto(s), + parent, }, // An instantiated item is monomorphic. Some(_) => ParamEnv { @@ -1043,6 +1075,7 @@ fn get_param_env<'tcx, S: UnderOwnerState<'tcx>>( ..generics }, predicates: GenericPredicates::default(), + parent, }, } } From b2d6177050bda0aba93f64f212d39d42686f8841 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 18 Jul 2025 20:56:13 +0200 Subject: [PATCH 40/51] full_def: cache instantiated translation --- frontend/exporter/src/state.rs | 16 +++--- frontend/exporter/src/types/def_id.rs | 12 +++-- frontend/exporter/src/types/new/full_def.rs | 57 +++++++++------------ 3 files changed, 37 insertions(+), 48 deletions(-) diff --git a/frontend/exporter/src/state.rs b/frontend/exporter/src/state.rs index 58791a496..2210f4adb 100644 --- a/frontend/exporter/src/state.rs +++ b/frontend/exporter/src/state.rs @@ -93,26 +93,22 @@ mod types { } /// Defines a mapping from types to types, for use with `TypeMap`. - pub struct FullDefMapper {} + pub struct FullDefMapper; impl TypeMapper for FullDefMapper { type Value = Arc>; } - /// Defines a mapping from types to types, for use with `TypeMap`. - pub struct PromotedFullDefsMapper {} - impl TypeMapper for PromotedFullDefsMapper { - type Value = HashMap>>; - } - /// Per-item cache #[derive(Default)] pub struct ItemCache<'tcx> { /// The translated `DefId`. pub def_id: Option, /// The translated definitions, generic in the Body kind. - pub full_def: TypeMap, - /// The Promoted constants of this body, if any. - pub promoteds: TypeMap, + /// Each rustc `DefId` gives several hax `DefId`s: one for each promoted constant (if any), + /// and the base one represented by `None`. Moreover we can instantiate definitions with + /// generic arguments. + pub full_defs: + HashMap<(Option, Option>), TypeMap>, /// Cache the `Ty` translations. pub tys: HashMap, Ty>, /// Cache the `ItemRef` translations. This is fast because `GenericArgsRef` is interned. diff --git a/frontend/exporter/src/types/def_id.rs b/frontend/exporter/src/types/def_id.rs index 7bb47e285..3c07a6667 100644 --- a/frontend/exporter/src/types/def_id.rs +++ b/frontend/exporter/src/types/def_id.rs @@ -206,10 +206,6 @@ impl DefId { index: rustc_hir::def_id::DefIndex::from_u32(index), } } - pub fn promoted_id(&self) -> Option { - let (_, _, promoted) = self.index; - promoted - } /// Iterate over this element and its parents. pub fn ancestry(&self) -> impl Iterator { @@ -255,6 +251,13 @@ impl DefId { } } +impl DefId { + pub fn promoted_id(&self) -> Option { + let (_, _, promoted) = self.index; + promoted + } +} + impl std::ops::Deref for DefId { type Target = DefIdContents; fn deref(&self) -> &Self::Target { @@ -290,6 +293,7 @@ impl std::hash::Hash for DefId { // the information. self.krate.hash(state); self.path.hash(state); + self.promoted_id().hash(state); } } diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 567734a7c..b5b16df1d 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -46,12 +46,11 @@ fn translate_full_def<'tcx, S, Body>( args: Option>, ) -> FullDef where - S: BaseState<'tcx>, + S: UnderOwnerState<'tcx>, Body: IsBody + TypeMappable, { let tcx = s.base().tcx; let rust_def_id = def_id.underlying_rust_def_id(); - let state_with_id = &s.with_owner_id(rust_def_id); let source_span; let attributes; let visibility; @@ -97,14 +96,12 @@ where let body = substitute(tcx, s.typing_env(), args, body); source_span = Some(body.span); - let ty: Ty = body.local_decls[rustc_middle::mir::Local::ZERO] - .ty - .sinto(state_with_id); + let ty: Ty = body.local_decls[rustc_middle::mir::Local::ZERO].ty.sinto(s); kind = FullDefKind::Const { param_env, ty, kind: ConstKind::PromotedConst, - body: Body::from_mir(state_with_id, body), + body: Body::from_mir(s, body), }; // None of these make sense for a promoted constant. @@ -121,7 +118,7 @@ where let this = if can_have_generics(tcx, rust_def_id) { let args_or_default = args.unwrap_or_else(|| ty::GenericArgs::identity_for_item(tcx, rust_def_id)); - let item = translate_item_ref(state_with_id, rust_def_id, args_or_default); + let item = translate_item_ref(s, rust_def_id, args_or_default); // Tricky: hax's DefId has more info (could be a promoted const), we must be careful to use // the input DefId instead of the one derived from `rust_def_id`. item.with_def_id(s, def_id) @@ -161,45 +158,36 @@ impl DefId { Body: IsBody + TypeMappable, S: BaseState<'tcx>, { - let rust_def_id = self.underlying_rust_def_id(); - if let Some(def) = s.with_item_cache(rust_def_id, |cache| match self.promoted_id() { - None => cache.full_def.get().cloned(), - Some(promoted_id) => cache.promoteds.or_default().get(&promoted_id).cloned(), - }) { - return def; - } - let def = Arc::new(translate_full_def(s, self, None)); - s.with_item_cache(rust_def_id, |cache| match self.promoted_id() { - None => { - cache.full_def.insert(def.clone()); - } - Some(promoted_id) => { - cache - .promoteds - .or_default() - .insert(promoted_id, def.clone()); - } - }); - def + self.full_def_maybe_instantiated(s, None) } /// Get the full definition of this item, instantiated if `args` is `Some`. pub fn full_def_maybe_instantiated<'tcx, S, Body>( &self, s: &S, - instantiate: Option>, + args: Option>, ) -> Arc> where Body: IsBody + TypeMappable, S: BaseState<'tcx>, { - match instantiate { - None => self.full_def(s), - Some(args) => { - // TODO: cache - Arc::new(translate_full_def(s, self, Some(args))) - } + let rust_def_id = self.underlying_rust_def_id(); + let s = &s.with_owner_id(rust_def_id); + let cache_key = (self.promoted_id(), args); + if let Some(def) = + s.with_cache(|cache| cache.full_defs.entry(cache_key).or_default().get().cloned()) + { + return def; } + let def = Arc::new(translate_full_def(s, self, args)); + s.with_cache(|cache| { + cache + .full_defs + .entry(cache_key) + .or_default() + .insert(def.clone()); + }); + def } } @@ -601,6 +589,7 @@ where ty::GenericArgs::identity_for_item(tcx, decl_def_id); let args = item_args.rebase_onto(tcx, def_id, trait_ref.args); + // TODO: is it the right `def_id`? let state_with_id = s.with_owner_id(def_id); solve_item_implied_traits(&state_with_id, decl_def_id, args) } else { From edbffed28f8be28f9751382979438bbb170d503e Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 18 Jul 2025 14:28:22 +0200 Subject: [PATCH 41/51] Translate arguments of implemented item in `AssocItem` --- frontend/exporter/src/types/ty.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index fad52eb56..0f12f9044 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -1733,16 +1733,15 @@ impl AssocItem { pub fn sfrom_instantiated<'tcx, S: BaseState<'tcx>>( s: &S, item: &ty::AssocItem, - args: Option>, + item_args: Option>, ) -> AssocItem { let tcx = s.base().tcx; // We want to solve traits in the context of this item. let s = &s.with_owner_id(item.def_id); + let item_args = + item_args.unwrap_or_else(|| ty::GenericArgs::identity_for_item(tcx, item.def_id)); let container_id = item.container_id(tcx); - let container_args = match args { - None => ty::GenericArgs::identity_for_item(tcx, container_id), - Some(args) => args.truncate_to(tcx, tcx.generics_of(container_id)), - }; + let container_args = item_args.truncate_to(tcx, tcx.generics_of(container_id)); let container = match item.container { ty::AssocItemContainer::Trait => { let trait_ref = @@ -1750,17 +1749,22 @@ impl AssocItem { AssocItemContainer::TraitContainer { trait_ref } } ty::AssocItemContainer::Impl => { - if let Some(implemented_trait_item) = item.trait_item_def_id { + if let Some(implemented_item_id) = item.trait_item_def_id { let item = translate_item_ref(s, container_id, container_args); let implemented_trait_ref = tcx .impl_trait_ref(container_id) .unwrap() .instantiate(tcx, container_args); + let implemented_trait_item = translate_item_ref( + s, + implemented_item_id, + item_args.rebase_onto(tcx, container_id, implemented_trait_ref.args), + ); AssocItemContainer::TraitImplContainer { impl_: item, implemented_trait_ref: implemented_trait_ref.sinto(s), - implemented_trait_item: implemented_trait_item.sinto(s), - overrides_default: tcx.defaultness(implemented_trait_item).has_value(), + implemented_trait_item, + overrides_default: tcx.defaultness(implemented_item_id).has_value(), } } else { AssocItemContainer::InherentImplContainer { @@ -1811,8 +1815,8 @@ pub enum AssocItemContainer { impl_: ItemRef, /// The trait ref implemented by the impl block. implemented_trait_ref: TraitRef, - /// The def_id of the associated item (in the trait declaration) that is being implemented. - implemented_trait_item: DefId, + /// The the associated item (in the trait declaration) that is being implemented. + implemented_trait_item: ItemRef, /// Whether the corresponding trait item had a default (and therefore this one overrides /// it). overrides_default: bool, From f46482cee299ae832b99467d471cd140ec6967fd Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 19 Jul 2025 12:08:01 +0200 Subject: [PATCH 42/51] Normalize after substituting --- frontend/exporter/src/body.rs | 3 ++- frontend/exporter/src/rustc_utils.rs | 22 ++++++++++++++++----- frontend/exporter/src/traits/utils.rs | 4 ++-- frontend/exporter/src/types/new/full_def.rs | 9 +++++---- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/frontend/exporter/src/body.rs b/frontend/exporter/src/body.rs index e1dd080ba..6ff26b6a1 100644 --- a/frontend/exporter/src/body.rs +++ b/frontend/exporter/src/body.rs @@ -228,8 +228,9 @@ mod module { instantiate: Option>, ) -> Option { let tcx = s.base().tcx; + let typing_env = s.typing_env(); MirKind::get_mir(tcx, did, |body| { - let body = substitute(tcx, instantiate, body.clone()); + let body = substitute(tcx, typing_env, instantiate, body.clone()); let body = Rc::new(body); body.sinto(&s.with_mir(body.clone())) }) diff --git a/frontend/exporter/src/rustc_utils.rs b/frontend/exporter/src/rustc_utils.rs index 2f8ef3d5c..59d89152e 100644 --- a/frontend/exporter/src/rustc_utils.rs +++ b/frontend/exporter/src/rustc_utils.rs @@ -4,23 +4,29 @@ use rustc_middle::{mir, ty}; pub fn inst_binder<'tcx, T>( tcx: ty::TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, args: Option>, x: ty::EarlyBinder<'tcx, T>, ) -> T where - T: ty::TypeFoldable>, + T: ty::TypeFoldable> + Clone, { match args { None => x.instantiate_identity(), - Some(args) => x.instantiate(tcx, args), + Some(args) => tcx.normalize_erasing_regions(typing_env, x.instantiate(tcx, args)), } } -pub fn substitute<'tcx, T>(tcx: ty::TyCtxt<'tcx>, args: Option>, x: T) -> T +pub fn substitute<'tcx, T>( + tcx: ty::TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + args: Option>, + x: T, +) -> T where T: ty::TypeFoldable>, { - inst_binder(tcx, args, ty::EarlyBinder::bind(x)) + inst_binder(tcx, typing_env, args, ty::EarlyBinder::bind(x)) } #[extension_traits::extension(pub trait SubstBinder)] @@ -108,7 +114,13 @@ pub trait HasParamEnv<'tcx> { impl<'tcx, S: UnderOwnerState<'tcx>> HasParamEnv<'tcx> for S { fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.base().tcx.param_env(self.owner_id()) + let tcx = self.base().tcx; + let def_id = self.owner_id(); + if can_have_generics(tcx, def_id) { + tcx.param_env(def_id) + } else { + ty::ParamEnv::empty() + } } fn typing_env(&self) -> ty::TypingEnv<'tcx> { ty::TypingEnv { diff --git a/frontend/exporter/src/traits/utils.rs b/frontend/exporter/src/traits/utils.rs index 242c33676..dbcd404f6 100644 --- a/frontend/exporter/src/traits/utils.rs +++ b/frontend/exporter/src/traits/utils.rs @@ -196,7 +196,7 @@ pub fn implied_predicates<'tcx>( /// Normalize a value. pub fn normalize<'tcx, T>(tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>, value: T) -> T where - T: TypeFoldable> + Copy, + T: TypeFoldable> + Clone, { use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::ObligationCause; @@ -204,7 +204,7 @@ where let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); infcx .at(&ObligationCause::dummy(), param_env) - .query_normalize(value) + .query_normalize(value.clone()) // We ignore the generated outlives relations. Unsure what we should do with them. .map(|x| x.value) .unwrap_or(value) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index b5b16df1d..c1a932734 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -430,7 +430,7 @@ where { let s = &s.with_owner_id(def_id); let tcx = s.base().tcx; - let type_of_self = || inst_binder(tcx, args, tcx.type_of(def_id)); + let type_of_self = || inst_binder(tcx, s.typing_env(), args, tcx.type_of(def_id)); let args_or_default = || args.unwrap_or_else(|| ty::GenericArgs::identity_for_item(tcx, def_id)); match get_def_kind(tcx, def_id) { @@ -516,7 +516,7 @@ where RDefKind::Impl { .. } => { use std::collections::HashMap; let param_env = get_param_env(s, args); - match inst_binder(tcx, args, tcx.impl_subject(def_id)) { + match inst_binder(tcx, s.typing_env(), args, tcx.impl_subject(def_id)) { ty::ImplSubject::Inherent(ty) => { let items = tcx .associated_items(def_id) @@ -638,7 +638,7 @@ where param_env: get_param_env(s, args), inline: tcx.codegen_fn_attrs(def_id).inline.sinto(s), is_const: tcx.constness(def_id) == rustc_hir::Constness::Const, - sig: inst_binder(tcx, args, tcx.fn_sig(def_id)).sinto(s), + sig: inst_binder(tcx, s.typing_env(), args, tcx.fn_sig(def_id)).sinto(s), body: get_body(s, args), }, RDefKind::AssocFn { .. } => FullDefKind::AssocFn { @@ -958,11 +958,12 @@ fn get_self_predicate<'tcx, S: UnderOwnerState<'tcx>>( ) -> TraitPredicate { use ty::Upcast; let tcx = s.base().tcx; + let typing_env = s.typing_env(); let pred: ty::TraitPredicate = crate::traits::self_predicate(tcx, s.owner_id()) .no_bound_vars() .unwrap() .upcast(tcx); - let pred = substitute(tcx, args, pred); + let pred = substitute(tcx, typing_env, args, pred); pred.sinto(s) } From 97c713fc5afe9212d101e7c2e77c16a0cf2d4de3 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 21 Jul 2025 15:16:57 +0200 Subject: [PATCH 43/51] ItemRef: add erasure capabilities --- frontend/exporter/src/types/ty.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/frontend/exporter/src/types/ty.rs b/frontend/exporter/src/types/ty.rs index 0f12f9044..0c5bab41e 100644 --- a/frontend/exporter/src/types/ty.rs +++ b/frontend/exporter/src/types/ty.rs @@ -462,6 +462,8 @@ pub struct ItemRefContents { /// If we're referring to a trait associated item, this gives the trait clause/impl we're /// referring to. pub in_trait: Option, + /// Whether this contains any reference to a type/lifetime/const parameter. + pub has_param: bool, } /// Reference to an item, with generics. Basically any mention of an item (function, type, etc) @@ -521,6 +523,7 @@ impl ItemRef { def_id: RDefId, generics: ty::GenericArgsRef<'tcx>, ) -> ItemRef { + use rustc_infer::infer::canonical::ir::TypeVisitableExt; let key = (def_id, generics); if let Some(item) = s.with_cache(|cache| cache.item_refs.get(&key).cloned()) { return item; @@ -562,6 +565,9 @@ impl ItemRef { generic_args, impl_exprs, in_trait: trait_info, + has_param: generics.has_param() + || generics.has_escaping_bound_vars() + || generics.has_free_regions(), }; let item = content.intern(s); s.with_cache(|cache| { @@ -581,6 +587,7 @@ impl ItemRef { generic_args: Default::default(), impl_exprs: Default::default(), in_trait: Default::default(), + has_param: false, }; let item = content.intern(s); s.with_global_cache(|cache| { @@ -591,6 +598,15 @@ impl ItemRef { item } + /// Erase lifetimes from the generic arguments of this item. + #[cfg(feature = "rustc")] + pub fn erase<'tcx, S: UnderOwnerState<'tcx>>(&self, s: &S) -> Self { + let def_id = self.def_id.underlying_rust_def_id(); + let args = self.rustc_args(s); + let args = erase_and_norm(s.base().tcx, s.typing_env(), args); + Self::translate(s, def_id, args).with_def_id(s, &self.def_id) + } + pub fn contents(&self) -> &ItemRefContents { &self.contents } From 60c354ffdf431398b8dd4e9deb7158fd8c0b55b2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 22 Jul 2025 13:29:06 +0200 Subject: [PATCH 44/51] Commit test outputs --- ...oolchain__attribute-opaque into-fstar.snap | 4 +- .../toolchain__attributes into-fstar.snap | 6 -- .../snapshots/toolchain__dyn into-fstar.snap | 1 - .../toolchain__functions into-fstar.snap | 1 - .../toolchain__generics into-fstar.snap | 1 - .../toolchain__include-flag into-coq.snap | 4 +- .../toolchain__include-flag into-fstar.snap | 4 +- .../toolchain__interface-only into-fstar.snap | 2 - .../toolchain__lean-tests into-lean.snap | 44 +++-------- ..._mut-ref-functionalization into-fstar.snap | 1 - .../toolchain__naming into-fstar.snap | 17 +---- .../toolchain__side-effects into-fstar.snap | 1 - .../toolchain__traits into-fstar.snap | 74 ++++++------------- 13 files changed, 41 insertions(+), 119 deletions(-) diff --git a/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap b/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap index 21d95b115..68770535e 100644 --- a/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap @@ -119,7 +119,6 @@ val ff_pre_post (x y: bool) result =. y) class t_T (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_U:Type0; f_c:u8; f_d_pre:Prims.unit -> Type0; @@ -134,8 +133,7 @@ class t_T (v_Self: Type0) = { val impl_T_for_u8:t_T u8 class t_TrGeneric (v_Self: Type0) (v_U: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; - [@@@ FStar.Tactics.Typeclasses.no_method]_super_17240578109911634293:Core.Clone.t_Clone v_U; + [@@@ FStar.Tactics.Typeclasses.no_method]_super_12400030861545157532:Core.Clone.t_Clone v_U; f_f_pre:v_U -> Type0; f_f_post:v_U -> v_Self -> Type0; f_f:x0: v_U -> Prims.Pure v_Self (f_f_pre x0) (fun result -> f_f_post x0 result) diff --git a/test-harness/src/snapshots/toolchain__attributes into-fstar.snap b/test-harness/src/snapshots/toolchain__attributes into-fstar.snap index 7dca84eb7..4b29f6b9a 100644 --- a/test-harness/src/snapshots/toolchain__attributes into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__attributes into-fstar.snap @@ -155,7 +155,6 @@ open Core open FStar.Mul class t_T (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_v_pre:v_Self -> Type0; f_v_post:x: v_Self -> x_future: v_Self -> pred: Type0{pred ==> true}; f_v:x0: v_Self -> Prims.Pure v_Self (f_v_pre x0) (fun result -> f_v_post x0 result) @@ -215,7 +214,6 @@ let impl_SafeIndex__as_usize (self: t_SafeIndex) : usize = self.f_i let impl_1 (#v_T: Type0) : Core.Ops.Index.t_Index (t_Array v_T (mk_usize 10)) t_SafeIndex = { f_Output = v_T; - f_Output_6696274936538609082 = FStar.Tactics.Typeclasses.solve; f_index_pre = (fun (self: t_Array v_T (mk_usize 10)) (index: t_SafeIndex) -> true); f_index_post = (fun (self: t_Array v_T (mk_usize 10)) (index: t_SafeIndex) (out: v_T) -> true); f_index = fun (self: t_Array v_T (mk_usize 10)) (index: t_SafeIndex) -> self.[ index.f_i ] @@ -252,7 +250,6 @@ open Core open FStar.Mul class t_Operation (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_double_pre:x: u8 -> pred: Type0 @@ -309,7 +306,6 @@ let impl_Operation_for_ViaMul: t_Operation t_ViaMul = } class t_TraitWithRequiresAndEnsures (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_method_pre:self_: v_Self -> x: u8 -> pred: Type0{x <. mk_u8 100 ==> pred}; f_method_post:self_: v_Self -> x: u8 -> r: u8 -> pred: Type0{pred ==> r >. mk_u8 88}; f_method:x0: v_Self -> x1: u8 @@ -404,7 +400,6 @@ let mutation_example let impl: Core.Ops.Index.t_Index t_MyArray usize = { f_Output = u8; - f_Output_6696274936538609082 = FStar.Tactics.Typeclasses.solve; f_index_pre = (fun (self_: t_MyArray) (index: usize) -> index <. v_MAX); f_index_post = (fun (self: t_MyArray) (index: usize) (out: u8) -> true); f_index = fun (self: t_MyArray) (index: usize) -> self.[ index ] @@ -593,7 +588,6 @@ open Core open FStar.Mul class t_Foo (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_f_pre:x: u8 -> y: u8 -> pred: Type0 diff --git a/test-harness/src/snapshots/toolchain__dyn into-fstar.snap b/test-harness/src/snapshots/toolchain__dyn into-fstar.snap index 75edb2282..916b17337 100644 --- a/test-harness/src/snapshots/toolchain__dyn into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__dyn into-fstar.snap @@ -33,7 +33,6 @@ open Core open FStar.Mul class t_Printable (v_Self: Type0) (v_S: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_stringify_pre:v_Self -> Type0; f_stringify_post:v_Self -> v_S -> Type0; f_stringify:x0: v_Self diff --git a/test-harness/src/snapshots/toolchain__functions into-fstar.snap b/test-harness/src/snapshots/toolchain__functions into-fstar.snap index f456755a4..df12b8b6e 100644 --- a/test-harness/src/snapshots/toolchain__functions into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__functions into-fstar.snap @@ -38,7 +38,6 @@ type t_CallableViaDeref = | CallableViaDeref : t_CallableViaDeref let impl: Core.Ops.Deref.t_Deref t_CallableViaDeref = { f_Target = Prims.unit -> bool; - f_Target_4695674276362814091 = FStar.Tactics.Typeclasses.solve; f_deref_pre = (fun (self: t_CallableViaDeref) -> true); f_deref_post = (fun (self: t_CallableViaDeref) (out: (Prims.unit -> bool)) -> true); f_deref diff --git a/test-harness/src/snapshots/toolchain__generics into-fstar.snap b/test-harness/src/snapshots/toolchain__generics into-fstar.snap index c75680dca..d42249d1c 100644 --- a/test-harness/src/snapshots/toolchain__generics into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__generics into-fstar.snap @@ -157,7 +157,6 @@ let call_g (_: Prims.unit) : usize = mk_usize 3 class t_Foo (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_const_add_pre:v_N: usize -> v_Self -> Type0; f_const_add_post:v_N: usize -> v_Self -> usize -> Type0; f_const_add:v_N: usize -> x0: v_Self diff --git a/test-harness/src/snapshots/toolchain__include-flag into-coq.snap b/test-harness/src/snapshots/toolchain__include-flag into-coq.snap index b6d4c8c65..e0f975a26 100644 --- a/test-harness/src/snapshots/toolchain__include-flag into-coq.snap +++ b/test-harness/src/snapshots/toolchain__include-flag into-coq.snap @@ -51,10 +51,10 @@ Record Foo_record : Type := #[export] Notation "'Foo_Foo_record'" := Build_Foo_record. -Class t_Trait (v_Self : Type) `{t_MetaSized (v_Self)} : Type := +Class t_Trait (v_Self : Type) : Type := { }. -Arguments t_Trait (_) {_}. +Arguments t_Trait (_). Instance t_Trait_572156424 : t_Trait ((t_Foo)) := { diff --git a/test-harness/src/snapshots/toolchain__include-flag into-fstar.snap b/test-harness/src/snapshots/toolchain__include-flag into-fstar.snap index 45ac83394..81212e6dd 100644 --- a/test-harness/src/snapshots/toolchain__include-flag into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__include-flag into-fstar.snap @@ -34,9 +34,7 @@ open FStar.Mul type t_Foo = | Foo : t_Foo -class t_Trait (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self -} +class t_Trait (v_Self: Type0) = { __marker_trait_t_Trait:Prims.unit } [@@ FStar.Tactics.Typeclasses.tcinstance] let impl: t_Trait t_Foo = { __marker_trait = () } diff --git a/test-harness/src/snapshots/toolchain__interface-only into-fstar.snap b/test-harness/src/snapshots/toolchain__interface-only into-fstar.snap index b8c5290cc..7d30bbb68 100644 --- a/test-harness/src/snapshots/toolchain__interface-only into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__interface-only into-fstar.snap @@ -101,7 +101,6 @@ unfold let ff_generic (v_X: usize) (#v_U: Type0) = ff_generic' v_X #v_U class t_T (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_Assoc:Type0; f_d_pre:Prims.unit -> Type0; f_d_post:Prims.unit -> Prims.unit -> Type0; @@ -119,7 +118,6 @@ let impl_T_for_u8: t_T u8 = } class t_T2 (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_d_pre:Prims.unit -> Type0; f_d_post:Prims.unit -> Prims.unit -> Type0; f_d:x0: Prims.unit -> Prims.Pure Prims.unit (f_d_pre x0) (fun result -> f_d_post x0 result) diff --git a/test-harness/src/snapshots/toolchain__lean-tests into-lean.snap b/test-harness/src/snapshots/toolchain__lean-tests into-lean.snap index de38d8c02..e1124f973 100644 --- a/test-harness/src/snapshots/toolchain__lean-tests into-lean.snap +++ b/test-harness/src/snapshots/toolchain__lean-tests into-lean.snap @@ -20,38 +20,12 @@ info: include_flag: ~ backend_options: ~ --- -exit = 0 -stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' - -[stdout] -diagnostics = [] - -[stdout.files] -"lean_tests.lean" = ''' --- Experimental lean backend for Hax --- Comment the following line to not import the prelude (requires the Lib.lean file) : -import Lib - - - --- unimplemented yet - -def FORTYTWO : usize := 42 - -def returns42 (_ : hax_Tuple0) : usize := FORTYTWO - -def add_two_numbers (x : usize) (y : usize) : usize := (hax_machine_int_add x y) - -def letBinding (x : usize) (y : usize) : usize := - let useless := (.constr_hax_Tuple0 : hax_Tuple0); - let result1 := (hax_machine_int_add x y); - let result2 := (hax_machine_int_add result1 2); - (hax_machine_int_add result2 1) - -def closure (_ : hax_Tuple0) : i32 := - let x := 41; - let f := (fun y => (hax_machine_int_add y x)); - (ops_function_Fn_call f - (.constr_hax_Tuple1 {hax_Tuple1_Tuple0 := 1} : (hax_Tuple1 i32))) - -abbrev UsizeAlias := usize''' +exit = 1 +stderr = """ +Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs + +thread 'main' panicked at rust-engine/src/ocaml_engine.rs:88:14: +called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: \"No such file or directory\" } +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +\u001B[1m\u001B[91merror\u001B[0m: \u001B[1mhax: hax-engine exited with non-zero code 101\u001B[0m""" +stdout = '' diff --git a/test-harness/src/snapshots/toolchain__mut-ref-functionalization into-fstar.snap b/test-harness/src/snapshots/toolchain__mut-ref-functionalization into-fstar.snap index 38d1d747b..ac5dff563 100644 --- a/test-harness/src/snapshots/toolchain__mut-ref-functionalization into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__mut-ref-functionalization into-fstar.snap @@ -269,7 +269,6 @@ let k (Alloc.Vec.t_Vec u8 Alloc.Alloc.t_Global & u16 & Prims.unit & u64) class t_FooTrait (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_z_pre:v_Self -> Type0; f_z_post:v_Self -> v_Self -> Type0; f_z:x0: v_Self -> Prims.Pure v_Self (f_z_pre x0) (fun result -> f_z_post x0 result) diff --git a/test-harness/src/snapshots/toolchain__naming into-fstar.snap b/test-harness/src/snapshots/toolchain__naming into-fstar.snap index 9ec3ce4a9..cd6dea444 100644 --- a/test-harness/src/snapshots/toolchain__naming into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__naming into-fstar.snap @@ -172,9 +172,7 @@ let reserved_names (v_val v_noeq v_of: u8) : u8 = (v_val +! v_noeq <: u8) +! v_o type t_Arity1 (v_T: Type0) = | Arity1 : v_T -> t_Arity1 v_T -class t_T1 (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self -} +class t_T1 (v_Self: Type0) = { __marker_trait_t_T1:Prims.unit } [@@ FStar.Tactics.Typeclasses.tcinstance] let impl_T1_for_Foo: t_T1 t_Foo = { __marker_trait = () } @@ -182,17 +180,13 @@ let impl_T1_for_Foo: t_T1 t_Foo = { __marker_trait = () } [@@ FStar.Tactics.Typeclasses.tcinstance] let impl_T1_for_tuple_Foo_u8: t_T1 (t_Foo & u8) = { __marker_trait = () } -class t_T2_for_a (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self -} +class t_T2_for_a (v_Self: Type0) = { __marker_trait_t_T2_for_a:Prims.unit } [@@ FStar.Tactics.Typeclasses.tcinstance] let impl_T2_ee_for_a_for_Arity1_of_tuple_Foo_u8: t_T2_for_a (t_Arity1 (t_Foo & u8)) = { __marker_trait = () } -class t_T3_ee_for_a (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self -} +class t_T3_ee_for_a (v_Self: Type0) = { __marker_trait_t_T3_ee_for_a:Prims.unit } [@@ FStar.Tactics.Typeclasses.tcinstance] let impl_T3_ee_e_for_a_for_Foo: t_T3_ee_for_a t_Foo = { __marker_trait = () } @@ -220,10 +214,7 @@ let construct_structs (a b: usize) : Prims.unit = let v_INHERENT_CONSTANT: usize = mk_usize 3 -class t_FooTrait (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; - f_ASSOCIATED_CONSTANT:usize -} +class t_FooTrait (v_Self: Type0) = { f_ASSOCIATED_CONSTANT:usize } let constants (#v_T: Type0) diff --git a/test-harness/src/snapshots/toolchain__side-effects into-fstar.snap b/test-harness/src/snapshots/toolchain__side-effects into-fstar.snap index 0a676481d..a92a71909 100644 --- a/test-harness/src/snapshots/toolchain__side-effects into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__side-effects into-fstar.snap @@ -34,7 +34,6 @@ open Core open FStar.Mul class t_MyFrom (v_Self: Type0) (v_T: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_my_from_pre:v_T -> Type0; f_my_from_post:v_T -> v_Self -> Type0; f_my_from:x0: v_T -> Prims.Pure v_Self (f_my_from_pre x0) (fun result -> f_my_from_post x0 result) diff --git a/test-harness/src/snapshots/toolchain__traits into-fstar.snap b/test-harness/src/snapshots/toolchain__traits into-fstar.snap index 3bac0d098..6b1ab5650 100644 --- a/test-harness/src/snapshots/toolchain__traits into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__traits into-fstar.snap @@ -32,19 +32,14 @@ module Traits.Block_size open Core open FStar.Mul -class t_BlockSizeUser (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; - f_BlockSize:Type0 -} +class t_BlockSizeUser (v_Self: Type0) = { f_BlockSize:Type0 } class t_ParBlocksSizeUser (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; - [@@@ FStar.Tactics.Typeclasses.no_method]_super_5884559561557426095:t_BlockSizeUser v_Self + [@@@ FStar.Tactics.Typeclasses.no_method]_super_6049459820240371831:t_BlockSizeUser v_Self } class t_BlockBackend (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; - [@@@ FStar.Tactics.Typeclasses.no_method]_super_17422710415653782164:t_ParBlocksSizeUser v_Self; + [@@@ FStar.Tactics.Typeclasses.no_method]_super_4483031398080819618:t_ParBlocksSizeUser v_Self; f_proc_block_pre:Alloc.Vec.t_Vec _ Alloc.Alloc.t_Global -> Type0; f_proc_block_post:Alloc.Vec.t_Vec _ Alloc.Alloc.t_Global -> Prims.unit -> Type0; f_proc_block:x0: Alloc.Vec.t_Vec _ Alloc.Alloc.t_Global @@ -57,13 +52,10 @@ module Traits.Default_traits_parameters open Core open FStar.Mul -class t_Bar (v_Self: Type0) (v_T: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self -} +class t_Bar (v_Self: Type0) (v_T: Type0) = { __marker_trait_t_Bar:Prims.unit } class t_Foo (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; - [@@@ FStar.Tactics.Typeclasses.no_method]_super_7275791365833186636:t_Bar v_Self f_U; + [@@@ FStar.Tactics.Typeclasses.no_method]_super_6177652678586986918:t_Bar v_Self f_U; f_U:Type0 } ''' @@ -73,9 +65,7 @@ module Traits.For_clauses.Issue_495_.Minimized_3_ open Core open FStar.Mul -class t_Trait (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self -} +class t_Trait (v_Self: Type0) = { __marker_trait_t_Trait:Prims.unit } [@@ FStar.Tactics.Typeclasses.tcinstance] let impl @@ -158,7 +148,6 @@ open Core open FStar.Mul class t_Foo (v_Self: Type0) (v_T: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_to_t_pre:v_Self -> Type0; f_to_t_post:v_Self -> v_T -> Type0; f_to_t:x0: v_Self -> Prims.Pure v_T (f_to_t_pre x0) (fun result -> f_to_t_post x0 result) @@ -175,14 +164,9 @@ module Traits.Impl_expr_in_goal open Core open FStar.Mul -class t_T1 (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; - f_Assoc:Type0 -} +class t_T1 (v_Self: Type0) = { f_Assoc:Type0 } -class t_T2 (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self -} +class t_T2 (v_Self: Type0) = { __marker_trait_t_T2:Prims.unit } [@@ FStar.Tactics.Typeclasses.tcinstance] let impl @@ -246,7 +230,6 @@ open Core open FStar.Mul class t_MyTrait (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_my_method_pre:v_Self -> Type0; f_my_method_post:v_Self -> Prims.unit -> Type0; f_my_method:x0: v_Self @@ -280,7 +263,6 @@ open FStar.Mul type t_Type (v_TypeArg: Type0) (v_ConstArg: usize) = { f_field:t_Array v_TypeArg v_ConstArg } class t_Trait (v_Self: Type0) (v_TypeArg: Type0) (v_ConstArg: usize) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_method_pre: #v_MethodTypeArg: Type0 -> v_MethodConstArg: usize -> @@ -443,12 +425,11 @@ let associated_function_caller () class t_SubTrait (v_Self: Type0) (v_TypeArg: Type0) (v_ConstArg: usize) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; - [@@@ FStar.Tactics.Typeclasses.no_method]_super_15145771689388873921:t_Trait v_Self + [@@@ FStar.Tactics.Typeclasses.no_method]_super_18031117442777819101:t_Trait v_Self v_TypeArg v_ConstArg; f_AssocType:Type0; - f_AssocType_2317355564376578742:t_Trait f_AssocType v_TypeArg v_ConstArg + f_AssocType_5661342272396313504:t_Trait f_AssocType v_TypeArg v_ConstArg } ''' "Traits.Interlaced_consts_types.fst" = ''' @@ -461,7 +442,6 @@ type t_Bar (v_FooConst: usize) (v_FooType: Type0) = | Bar : t_Array v_FooType v_FooConst -> t_Bar v_FooConst v_FooType class t_Foo (v_Self: Type0) (v_FooConst: usize) (v_FooType: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_fun_pre: v_FunConst: usize -> #v_FunType: Type0 -> @@ -525,14 +505,12 @@ open Core open FStar.Mul class t_Trait1 (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_T:Type0; - f_T_7969211799618487585:t_Trait1 f_T + f_T_5587126706995160828:t_Trait1 f_T } class t_Trait2 (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; - [@@@ FStar.Tactics.Typeclasses.no_method]_super_3259985701465885527:t_Trait1 v_Self; + [@@@ FStar.Tactics.Typeclasses.no_method]_super_6380933412563503442:t_Trait1 v_Self; f_U:Type0 } ''' @@ -552,7 +530,6 @@ open Core open FStar.Mul class t_PolyOp (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_op_pre:u32 -> u32 -> Type0; f_op_post:u32 -> u32 -> u32 -> Type0; f_op:x0: u32 -> x1: u32 -> Prims.Pure u32 (f_op_pre x0 x1) (fun result -> f_op_post x0 x1 result) @@ -590,8 +567,7 @@ open Core open FStar.Mul class t_SuperTrait (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; - [@@@ FStar.Tactics.Typeclasses.no_method]_super_15837849249852401974:Core.Clone.t_Clone v_Self; + [@@@ FStar.Tactics.Typeclasses.no_method]_super_14156401398203956914:Core.Clone.t_Clone v_Self; f_function_of_super_trait_pre:v_Self -> Type0; f_function_of_super_trait_post:v_Self -> u32 -> Type0; f_function_of_super_trait:x0: v_Self @@ -603,7 +579,7 @@ class t_SuperTrait (v_Self: Type0) = { [@@ FStar.Tactics.Typeclasses.tcinstance] let impl: t_SuperTrait i32 = { - _super_15837849249852401974 = FStar.Tactics.Typeclasses.solve; + _super_14156401398203956914 = FStar.Tactics.Typeclasses.solve; f_function_of_super_trait_pre = (fun (self: i32) -> true); f_function_of_super_trait_post = (fun (self: i32) (out: u32) -> true); f_function_of_super_trait = fun (self: i32) -> cast (Core.Num.impl_i32__abs self <: i32) <: u32 @@ -612,7 +588,6 @@ let impl: t_SuperTrait i32 = type t_Struct = | Struct : t_Struct class t_Bar (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_bar_pre:v_Self -> Type0; f_bar_post:v_Self -> Prims.unit -> Type0; f_bar:x0: v_Self -> Prims.Pure Prims.unit (f_bar_pre x0) (fun result -> f_bar_post x0 result) @@ -679,9 +654,8 @@ let uuse_iimpl_trait (_: Prims.unit) : Prims.unit = () class t_Foo (v_Self: Type0) = { - [@@@ FStar.Tactics.Typeclasses.no_method]_super_4726684624731801277:Core.Marker.t_MetaSized v_Self; f_AssocType:Type0; - f_AssocType_1162045947544099865:t_SuperTrait f_AssocType; + f_AssocType_3062811437891594152:t_SuperTrait f_AssocType; f_N:usize; f_assoc_f_pre:Prims.unit -> Type0; f_assoc_f_post:Prims.unit -> Prims.unit -> Type0; @@ -692,17 +666,17 @@ class t_Foo (v_Self: Type0) = { f_method_f:x0: v_Self -> Prims.Pure Prims.unit (f_method_f_pre x0) (fun result -> f_method_f_post x0 result); f_assoc_type_pre: - {| i2: Core.Marker.t_Copy v_5081411602995720689.f_AssocType |} -> - v_5081411602995720689.f_AssocType + {| i2: Core.Marker.t_Copy v_16903484722429324329.f_AssocType |} -> + v_16903484722429324329.f_AssocType -> Type0; f_assoc_type_post: - {| i2: Core.Marker.t_Copy v_5081411602995720689.f_AssocType |} -> - v_5081411602995720689.f_AssocType -> + {| i2: Core.Marker.t_Copy v_16903484722429324329.f_AssocType |} -> + v_16903484722429324329.f_AssocType -> Prims.unit -> Type0; f_assoc_type: - {| i2: Core.Marker.t_Copy v_5081411602995720689.f_AssocType |} -> - x0: v_5081411602995720689.f_AssocType + {| i2: Core.Marker.t_Copy v_16903484722429324329.f_AssocType |} -> + x0: v_16903484722429324329.f_AssocType -> Prims.Pure Prims.unit (f_assoc_type_pre #i2 x0) (fun result -> f_assoc_type_post #i2 x0 result) @@ -711,9 +685,9 @@ class t_Foo (v_Self: Type0) = { class t_Lang (v_Self: Type0) = { f_Var:Type0; f_s_pre:v_Self -> i32 -> Type0; - f_s_post:v_Self -> i32 -> (v_Self & v_178762381425797165.f_Var) -> Type0; + f_s_post:v_Self -> i32 -> (v_Self & v_2438024169610850509.f_Var) -> Type0; f_s:x0: v_Self -> x1: i32 - -> Prims.Pure (v_Self & v_178762381425797165.f_Var) + -> Prims.Pure (v_Self & v_2438024169610850509.f_Var) (f_s_pre x0 x1) (fun result -> f_s_post x0 x1 result) } @@ -729,7 +703,7 @@ let g (#v_T: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] i1: t_Foo v_T) (x let impl_Foo_for_tuple_: t_Foo Prims.unit = { f_AssocType = i32; - f_AssocType_1162045947544099865 = FStar.Tactics.Typeclasses.solve; + f_AssocType_3062811437891594152 = FStar.Tactics.Typeclasses.solve; f_N = mk_usize 32; f_assoc_f_pre = (fun (_: Prims.unit) -> true); f_assoc_f_post = (fun (_: Prims.unit) (out: Prims.unit) -> true); From b2a2a298d97ebfcc24b15138559492de89a1315c Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 28 Jul 2025 10:09:44 +0200 Subject: [PATCH 45/51] fix(rengine): respect env var `HAX_ENGINE_BINARY` --- rust-engine/src/ocaml_engine.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/rust-engine/src/ocaml_engine.rs b/rust-engine/src/ocaml_engine.rs index 7d45c9f2a..3c6357766 100644 --- a/rust-engine/src/ocaml_engine.rs +++ b/rust-engine/src/ocaml_engine.rs @@ -80,12 +80,13 @@ impl Query { }; } - let mut engine_subprocess = Command::new("hax-engine") - .arg("driver_rust_engine") - .stdin(std::process::Stdio::piped()) - .stdout(std::process::Stdio::piped()) - .spawn() - .unwrap(); + let mut engine_subprocess = + Command::new(std::env::var("HAX_ENGINE_BINARY").unwrap_or("hax-engine".into())) + .arg("driver_rust_engine") + .stdin(std::process::Stdio::piped()) + .stdout(std::process::Stdio::piped()) + .spawn() + .unwrap(); let mut stdin = std::io::BufWriter::new( engine_subprocess From 4952add5b70a10bf9155ce896028bc4ed6fc06cf Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 28 Jul 2025 10:11:21 +0200 Subject: [PATCH 46/51] chore: refresh tests --- .../toolchain__lean-tests into-lean.snap | 44 +++++++-- .../toolchain__traits into-fstar.snap | 93 +++++++++++++++---- 2 files changed, 109 insertions(+), 28 deletions(-) diff --git a/test-harness/src/snapshots/toolchain__lean-tests into-lean.snap b/test-harness/src/snapshots/toolchain__lean-tests into-lean.snap index e1124f973..de38d8c02 100644 --- a/test-harness/src/snapshots/toolchain__lean-tests into-lean.snap +++ b/test-harness/src/snapshots/toolchain__lean-tests into-lean.snap @@ -20,12 +20,38 @@ info: include_flag: ~ backend_options: ~ --- -exit = 1 -stderr = """ -Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs - -thread 'main' panicked at rust-engine/src/ocaml_engine.rs:88:14: -called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: \"No such file or directory\" } -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -\u001B[1m\u001B[91merror\u001B[0m: \u001B[1mhax: hax-engine exited with non-zero code 101\u001B[0m""" -stdout = '' +exit = 0 +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' + +[stdout] +diagnostics = [] + +[stdout.files] +"lean_tests.lean" = ''' +-- Experimental lean backend for Hax +-- Comment the following line to not import the prelude (requires the Lib.lean file) : +import Lib + + + +-- unimplemented yet + +def FORTYTWO : usize := 42 + +def returns42 (_ : hax_Tuple0) : usize := FORTYTWO + +def add_two_numbers (x : usize) (y : usize) : usize := (hax_machine_int_add x y) + +def letBinding (x : usize) (y : usize) : usize := + let useless := (.constr_hax_Tuple0 : hax_Tuple0); + let result1 := (hax_machine_int_add x y); + let result2 := (hax_machine_int_add result1 2); + (hax_machine_int_add result2 1) + +def closure (_ : hax_Tuple0) : i32 := + let x := 41; + let f := (fun y => (hax_machine_int_add y x)); + (ops_function_Fn_call f + (.constr_hax_Tuple1 {hax_Tuple1_Tuple0 := 1} : (hax_Tuple1 i32))) + +abbrev UsizeAlias := usize''' diff --git a/test-harness/src/snapshots/toolchain__traits into-fstar.snap b/test-harness/src/snapshots/toolchain__traits into-fstar.snap index 6b1ab5650..6634e2616 100644 --- a/test-harness/src/snapshots/toolchain__traits into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__traits into-fstar.snap @@ -153,7 +153,7 @@ class t_Foo (v_Self: Type0) (v_T: Type0) = { f_to_t:x0: v_Self -> Prims.Pure v_T (f_to_t_pre x0) (fun result -> f_to_t_post x0 result) } -let e_f (#v_X: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] i1: t_Foo v_X u8) (x: v_X) +let e_f (#v_X: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] i0: t_Foo v_X u8) (x: v_X) : Prims.unit = let _:u8 = f_to_t #v_X #u8 #FStar.Tactics.Typeclasses.solve x in () @@ -171,8 +171,8 @@ class t_T2 (v_Self: Type0) = { __marker_trait_t_T2:Prims.unit } [@@ FStar.Tactics.Typeclasses.tcinstance] let impl (#v_U: Type0) - (#[FStar.Tactics.Typeclasses.tcresolve ()] i1: t_T1 v_U) - (#[FStar.Tactics.Typeclasses.tcresolve ()] i2: t_T2 i1.f_Assoc) + (#[FStar.Tactics.Typeclasses.tcresolve ()] i0: t_T1 v_U) + (#[FStar.Tactics.Typeclasses.tcresolve ()] i1: t_T2 i0.f_Assoc) : t_T2 v_U = { __marker_trait = () } ''' "Traits.Implement_arithmetic_trait.fst" = ''' @@ -384,7 +384,7 @@ let method_caller (#v_MethodTypeArg #v_TypeArg: Type0) (v_ConstArg v_MethodConstArg: usize) (#v_ImplTrait: Type0) - (#[FStar.Tactics.Typeclasses.tcresolve ()] i3: t_Trait v_ImplTrait v_TypeArg v_ConstArg) + (#[FStar.Tactics.Typeclasses.tcresolve ()] i0: t_Trait v_ImplTrait v_TypeArg v_ConstArg) (x: v_ImplTrait) (value_TypeArg: v_TypeArg) (value_Type: t_Type v_TypeArg v_ConstArg) @@ -406,7 +406,7 @@ let associated_function_caller (#v_MethodTypeArg #v_TypeArg: Type0) (v_ConstArg v_MethodConstArg: usize) (#v_ImplTrait: Type0) - (#[FStar.Tactics.Typeclasses.tcresolve ()] i3: t_Trait v_ImplTrait v_TypeArg v_ConstArg) + (#[FStar.Tactics.Typeclasses.tcresolve ()] i0: t_Trait v_ImplTrait v_TypeArg v_ConstArg) (x: v_ImplTrait) (value_TypeArg: v_TypeArg) (value_Type: t_Type v_TypeArg v_ConstArg) @@ -520,9 +520,64 @@ module Traits.Type_alias_bounds_issue_707_ open Core open FStar.Mul -type t_StructWithGenericBounds (v_T: Type0) {| i1: Core.Clone.t_Clone v_T |} = +type t_StructWithGenericBounds (v_T: Type0) {| i0: Core.Clone.t_Clone v_T |} = | StructWithGenericBounds : v_T -> t_StructWithGenericBounds v_T ''' +"Traits.Typenum_perf.fst" = ''' +module Traits.Typenum_perf +#set-options "--fuel 0 --ifuel 1 --z3rlimit 15" +open Core +open FStar.Mul + +let _ = + (* This module has implicit dependencies, here we make them explicit. *) + (* The implicit dependencies arise from typeclasses instances. *) + let open Typenum.Type_operators in + () + +let e_f + (#v_T: Type0) + (#[FStar.Tactics.Typeclasses.tcresolve ()] + i0: + Typenum.Type_operators.t_IsLess v_T + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + (Typenum.Uint.t_UInt + Typenum.Uint.t_UTerm + Typenum.Bit.t_B1 + ) + Typenum.Bit.t_B1 + ) + Typenum.Bit.t_B1 + ) Typenum.Bit.t_B1) + Typenum.Bit.t_B1) + Typenum.Bit.t_B1) + Typenum.Bit.t_B1) + Typenum.Bit.t_B1) Typenum.Bit.t_B1) + Typenum.Bit.t_B1) Typenum.Bit.t_B1) + Typenum.Bit.t_B1) Typenum.Bit.t_B1) Typenum.Bit.t_B1 + ) Typenum.Bit.t_B1) Typenum.Bit.t_B1) Typenum.Bit.t_B1) + Typenum.Bit.t_B1) Typenum.Bit.t_B1) Typenum.Bit.t_B1)) + (_: Prims.unit) + : Prims.unit = () +''' "Traits.Unconstrainted_types_issue_677_.fst" = ''' module Traits.Unconstrainted_types_issue_677_ #set-options "--fuel 0 --ifuel 1 --z3rlimit 15" @@ -555,7 +610,7 @@ let impl_PolyOp_for_Times: t_PolyOp t_Times = f_op = fun (x: u32) (y: u32) -> x *! y } -let twice (#v_OP: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] i1: t_PolyOp v_OP) (x: u32) +let twice (#v_OP: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] i0: t_PolyOp v_OP) (x: u32) : u32 = f_op #v_OP #FStar.Tactics.Typeclasses.solve x x let both (x: u32) : (u32 & u32) = twice #t_Plus x, twice #t_Times x <: (u32 & u32) @@ -593,12 +648,12 @@ class t_Bar (v_Self: Type0) = { f_bar:x0: v_Self -> Prims.Pure Prims.unit (f_bar_pre x0) (fun result -> f_bar_post x0 result) } -let impl_2__method (#v_T: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] i1: t_Bar v_T) (x: v_T) +let impl_2__method (#v_T: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] i0: t_Bar v_T) (x: v_T) : Prims.unit = f_bar #v_T #FStar.Tactics.Typeclasses.solve x let cclosure_iimpl_expr (#v_I: Type0) - (#[FStar.Tactics.Typeclasses.tcresolve ()] i1: Core.Iter.Traits.Iterator.t_Iterator v_I) + (#[FStar.Tactics.Typeclasses.tcresolve ()] i0: Core.Iter.Traits.Iterator.t_Iterator v_I) (it: v_I) : Alloc.Vec.t_Vec Prims.unit Alloc.Alloc.t_Global = Core.Iter.Traits.Iterator.f_collect #(Core.Iter.Adapters.Map.t_Map v_I (Prims.unit -> Prims.unit)) @@ -614,8 +669,8 @@ let cclosure_iimpl_expr let cclosure_iimpl_expr_fngen (#v_I #v_F: Type0) - (#[FStar.Tactics.Typeclasses.tcresolve ()] i2: Core.Iter.Traits.Iterator.t_Iterator v_I) - (#[FStar.Tactics.Typeclasses.tcresolve ()] i3: Core.Ops.Function.t_FnMut v_F Prims.unit) + (#[FStar.Tactics.Typeclasses.tcresolve ()] i0: Core.Iter.Traits.Iterator.t_Iterator v_I) + (#[FStar.Tactics.Typeclasses.tcresolve ()] i1: Core.Ops.Function.t_FnMut v_F Prims.unit) (it: v_I) (f: v_F) : Alloc.Vec.t_Vec Prims.unit Alloc.Alloc.t_Global = @@ -666,20 +721,20 @@ class t_Foo (v_Self: Type0) = { f_method_f:x0: v_Self -> Prims.Pure Prims.unit (f_method_f_pre x0) (fun result -> f_method_f_post x0 result); f_assoc_type_pre: - {| i2: Core.Marker.t_Copy v_16903484722429324329.f_AssocType |} -> + {| i1: Core.Marker.t_Copy v_16903484722429324329.f_AssocType |} -> v_16903484722429324329.f_AssocType -> Type0; f_assoc_type_post: - {| i2: Core.Marker.t_Copy v_16903484722429324329.f_AssocType |} -> + {| i1: Core.Marker.t_Copy v_16903484722429324329.f_AssocType |} -> v_16903484722429324329.f_AssocType -> Prims.unit -> Type0; f_assoc_type: - {| i2: Core.Marker.t_Copy v_16903484722429324329.f_AssocType |} -> + {| i1: Core.Marker.t_Copy v_16903484722429324329.f_AssocType |} -> x0: v_16903484722429324329.f_AssocType -> Prims.Pure Prims.unit - (f_assoc_type_pre #i2 x0) - (fun result -> f_assoc_type_post #i2 x0 result) + (f_assoc_type_pre #i1 x0) + (fun result -> f_assoc_type_post #i1 x0 result) } class t_Lang (v_Self: Type0) = { @@ -692,12 +747,12 @@ class t_Lang (v_Self: Type0) = { (fun result -> f_s_post x0 x1 result) } -let f (#v_T: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] i1: t_Foo v_T) (x: v_T) : Prims.unit = +let f (#v_T: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] i0: t_Foo v_T) (x: v_T) : Prims.unit = let _:Prims.unit = f_assoc_f #v_T #FStar.Tactics.Typeclasses.solve () in f_method_f #v_T #FStar.Tactics.Typeclasses.solve x -let g (#v_T: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] i1: t_Foo v_T) (x: i1.f_AssocType) - : u32 = f_function_of_super_trait #i1.f_AssocType #FStar.Tactics.Typeclasses.solve x +let g (#v_T: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] i0: t_Foo v_T) (x: i0.f_AssocType) + : u32 = f_function_of_super_trait #i0.f_AssocType #FStar.Tactics.Typeclasses.solve x [@@ FStar.Tactics.Typeclasses.tcinstance] let impl_Foo_for_tuple_: t_Foo Prims.unit = From f68b3ab26f8a2dd6a34b502ca168bedffd95e6dd Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 28 Jul 2025 10:21:18 +0200 Subject: [PATCH 47/51] chore: update rustc-coverage-tests --- rustc-coverage-tests/snapshots/fstar/Coverage.No_spans.fst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rustc-coverage-tests/snapshots/fstar/Coverage.No_spans.fst b/rustc-coverage-tests/snapshots/fstar/Coverage.No_spans.fst index 6ff9de18b..7f198d144 100644 --- a/rustc-coverage-tests/snapshots/fstar/Coverage.No_spans.fst +++ b/rustc-coverage-tests/snapshots/fstar/Coverage.No_spans.fst @@ -10,10 +10,9 @@ let affected_function (_: Prims.unit) : Prims.unit -> Prims.unit = let main (_: Prims.unit) : Prims.unit = let _:Prims.unit = - Core.Ops.Function.f_call #_ - #Prims.unit + Core.Ops.Function.f_call #Prims.unit #FStar.Tactics.Typeclasses.solve - (affected_function () <: _) + (affected_function () <: Prims.unit -> Prims.unit) (() <: Prims.unit) in () From 108105f1327d04c8258254c3b1a93dd958660b22 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 29 Jul 2025 11:16:11 +0200 Subject: [PATCH 48/51] fix: typo Co-authored-by: Lucas Franceschino --- frontend/exporter/src/types/new/full_def.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 36a5f1a96..6596a0994 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -821,7 +821,7 @@ pub struct VirtualTraitImpl { pub trait_pred: TraitPredicate, /// The `ImplExpr`s required to satisfy the predicates on the trait declaration. pub implied_impl_exprs: Vec, - /// Tye associated types and their predicates, in definition order. + /// The associated types and their predicates, in definition order. pub types: Vec<(Ty, Vec)>, } From 18727c363fea40a1a84377bf3d80b0fb4ece90ee Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Tue, 9 Sep 2025 08:56:40 +0200 Subject: [PATCH 49/51] chore: update changlelog --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5021e8f41..b7b7193c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,17 @@ Change to the Rust Engine: - Add a resugaring `FunctionsToConstants` (#1559) - Drop the tuple nodes of the AST, add resugaring node for tuples (#1662) +Changes to the frontend: +- Add an explicit `Self: Trait` clause to trait methods and consts (#1559) +- Fix `ImplExpr::Builtin` that had some type errors (#1559) +- Improve the translation of `Drop` information (#1559) +- Add variance information to type parameters (#1559) +- Cleanup the `State` infrastructure a little bit (#1559) +- Add information about the metadata to use in unsize coercions (#1559) +- Resolve `dyn Trait` predicates (#1559) +- Many improvements to `FullDef` (#1559) +- Add infrastructure to get a monomorphized `FullDef`; this is used in charon to monomorphize a crate graph (#1559) + Miscellaneous: - A lean tutorial has been added to the hax website. From 1df28c4bbb52a744bb604a27eee237a10b447d14 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 28 Jul 2025 13:00:14 +0200 Subject: [PATCH 50/51] fix(engine): rewrite `Self` --- engine/backends/fstar/fstar_backend.ml | 37 ++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/engine/backends/fstar/fstar_backend.ml b/engine/backends/fstar/fstar_backend.ml index 276314711..b523b4585 100644 --- a/engine/backends/fstar/fstar_backend.ml +++ b/engine/backends/fstar/fstar_backend.ml @@ -2003,6 +2003,42 @@ let unsize_as_identity = in visitor#visit_item () +(** Rewrites, in trait, local bounds refereing to `Self` into the impl expr of + kind `Self`. *) +let local_self_bound_as_self (i : AST.item) : AST.item = + match i.v with + | Trait { name; generics; _ } -> + let generic_eq (param : generic_param) (value : generic_value) = + (let* id = + match (param.kind, value) with + | GPConst _, GConst { e = LocalVar id } -> Some id + | GPType, GType (TParam id) -> Some id + | GPLifetime _, GLifetime _ -> Some param.ident + | _ -> None + in + Some ([%eq: local_ident] id param.ident)) + |> Option.value ~default:false + in + let generics_eq params values = + match List.for_all2 ~f:generic_eq params values with + | List.Or_unequal_lengths.Ok v -> v + | List.Or_unequal_lengths.Unequal_lengths -> false + in + (object + inherit [_] U.Visitors.map as super + + method! visit_impl_expr () ie = + match ie with + | { kind = LocalBound _; goal = { args; trait } } + when [%eq: concrete_ident] trait name + && generics_eq generics.params args -> + { ie with kind = Self } + | _ -> ie + end) + #visit_item + () i + | _ -> i + let apply_phases (bo : BackendOptions.t) (items : Ast.Rust.item list) : AST.item list = let items = @@ -2022,6 +2058,7 @@ let apply_phases (bo : BackendOptions.t) (items : Ast.Rust.item list) : TransformToInputLanguage.ditems items |> List.map ~f:unsize_as_identity |> List.map ~f:unsize_as_identity + |> List.map ~f:local_self_bound_as_self |> List.map ~f:U.Mappers.add_typ_ascription in items From 3a546343489c1a3b14795ed8cc57414424edfbc0 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Tue, 9 Sep 2025 09:04:55 +0200 Subject: [PATCH 51/51] chore: update test snapshots --- ...oolchain__attribute-opaque into-fstar.snap | 2 +- .../toolchain__traits into-fstar.snap | 33 +++++++------------ tests/Cargo.lock | 12 +++---- 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap b/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap index a9fa9fab2..6c822974e 100644 --- a/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap @@ -140,7 +140,7 @@ class t_TrGeneric (v_Self: Type0) (v_U: Type0) = { } [@@ FStar.Tactics.Typeclasses.tcinstance] -let _ = fun (v_Self:Type0) (v_U:Type0) {|i: t_TrGeneric v_Self v_U|} -> i._super_17240578109911634293 +let _ = fun (v_Self:Type0) (v_U:Type0) {|i: t_TrGeneric v_Self v_U|} -> i._super_12400030861545157532 [@@ FStar.Tactics.Typeclasses.tcinstance] val impl_2 (#v_U: Type0) {| i0: Core.Clone.t_Clone v_U |} : t_TrGeneric i32 v_U diff --git a/test-harness/src/snapshots/toolchain__traits into-fstar.snap b/test-harness/src/snapshots/toolchain__traits into-fstar.snap index 52bffe5e8..297b54b07 100644 --- a/test-harness/src/snapshots/toolchain__traits into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__traits into-fstar.snap @@ -39,7 +39,7 @@ class t_ParBlocksSizeUser (v_Self: Type0) = { } [@@ FStar.Tactics.Typeclasses.tcinstance] -let _ = fun (v_Self:Type0) {|i: t_ParBlocksSizeUser v_Self|} -> i._super_5884559561557426095 +let _ = fun (v_Self:Type0) {|i: t_ParBlocksSizeUser v_Self|} -> i._super_6049459820240371831 class t_BlockBackend (v_Self: Type0) = { [@@@ FStar.Tactics.Typeclasses.no_method]_super_4483031398080819618:t_ParBlocksSizeUser v_Self; @@ -50,7 +50,7 @@ class t_BlockBackend (v_Self: Type0) = { } [@@ FStar.Tactics.Typeclasses.tcinstance] -let _ = fun (v_Self:Type0) {|i: t_BlockBackend v_Self|} -> i._super_17422710415653782164 +let _ = fun (v_Self:Type0) {|i: t_BlockBackend v_Self|} -> i._super_4483031398080819618 ''' "Traits.Default_traits_parameters.fst" = ''' module Traits.Default_traits_parameters @@ -66,7 +66,7 @@ class t_Foo (v_Self: Type0) = { } [@@ FStar.Tactics.Typeclasses.tcinstance] -let _ = fun (v_Self:Type0) {|i: t_Foo v_Self|} -> i._super_7275791365833186636 +let _ = fun (v_Self:Type0) {|i: t_Foo v_Self|} -> i._super_6177652678586986918 ''' "Traits.For_clauses.Issue_495_.Minimized_3_.fst" = ''' module Traits.For_clauses.Issue_495_.Minimized_3_ @@ -442,7 +442,7 @@ class t_SubTrait (v_Self: Type0) (v_TypeArg: Type0) (v_ConstArg: usize) = { } [@@ FStar.Tactics.Typeclasses.tcinstance] -let _ = fun (v_Self:Type0) (v_TypeArg:Type0) (v_ConstArg:usize) {|i: t_SubTrait v_Self v_TypeArg v_ConstArg|} -> i._super_15145771689388873921 +let _ = fun (v_Self:Type0) (v_TypeArg:Type0) (v_ConstArg:usize) {|i: t_SubTrait v_Self v_TypeArg v_ConstArg|} -> i._super_18031117442777819101 ''' "Traits.Interlaced_consts_types.fst" = ''' module Traits.Interlaced_consts_types @@ -527,7 +527,7 @@ class t_Trait2 (v_Self: Type0) = { } [@@ FStar.Tactics.Typeclasses.tcinstance] -let _ = fun (v_Self:Type0) {|i: t_Trait2 v_Self|} -> i._super_3259985701465885527 +let _ = fun (v_Self:Type0) {|i: t_Trait2 v_Self|} -> i._super_6380933412563503442 ''' "Traits.Type_alias_bounds_issue_707_.fst" = ''' module Traits.Type_alias_bounds_issue_707_ @@ -647,7 +647,7 @@ class t_SuperTrait (v_Self: Type0) = { } [@@ FStar.Tactics.Typeclasses.tcinstance] -let _ = fun (v_Self:Type0) {|i: t_SuperTrait v_Self|} -> i._super_15837849249852401974 +let _ = fun (v_Self:Type0) {|i: t_SuperTrait v_Self|} -> i._super_14156401398203956914 [@@ FStar.Tactics.Typeclasses.tcinstance] let impl: t_SuperTrait i32 = @@ -738,18 +738,9 @@ class t_Foo (v_Self: Type0) = { f_method_f_post:v_Self -> Prims.unit -> Type0; f_method_f:x0: v_Self -> Prims.Pure Prims.unit (f_method_f_pre x0) (fun result -> f_method_f_post x0 result); - f_assoc_type_pre: - {| i1: Core.Marker.t_Copy v_16903484722429324329.f_AssocType |} -> - v_16903484722429324329.f_AssocType - -> Type0; - f_assoc_type_post: - {| i1: Core.Marker.t_Copy v_16903484722429324329.f_AssocType |} -> - v_16903484722429324329.f_AssocType -> - Prims.unit - -> Type0; - f_assoc_type: - {| i1: Core.Marker.t_Copy v_16903484722429324329.f_AssocType |} -> - x0: v_16903484722429324329.f_AssocType + f_assoc_type_pre:{| i1: Core.Marker.t_Copy f_AssocType |} -> f_AssocType -> Type0; + f_assoc_type_post:{| i1: Core.Marker.t_Copy f_AssocType |} -> f_AssocType -> Prims.unit -> Type0; + f_assoc_type:{| i1: Core.Marker.t_Copy f_AssocType |} -> x0: f_AssocType -> Prims.Pure Prims.unit (f_assoc_type_pre #i1 x0) (fun result -> f_assoc_type_post #i1 x0 result) @@ -758,11 +749,9 @@ class t_Foo (v_Self: Type0) = { class t_Lang (v_Self: Type0) = { f_Var:Type0; f_s_pre:v_Self -> i32 -> Type0; - f_s_post:v_Self -> i32 -> (v_Self & v_2438024169610850509.f_Var) -> Type0; + f_s_post:v_Self -> i32 -> (v_Self & f_Var) -> Type0; f_s:x0: v_Self -> x1: i32 - -> Prims.Pure (v_Self & v_2438024169610850509.f_Var) - (f_s_pre x0 x1) - (fun result -> f_s_post x0 x1 result) + -> Prims.Pure (v_Self & f_Var) (f_s_pre x0 x1) (fun result -> f_s_post x0 x1 result) } let f (#v_T: Type0) (#[FStar.Tactics.Typeclasses.tcresolve ()] i0: t_Foo v_T) (x: v_T) : Prims.unit = diff --git a/tests/Cargo.lock b/tests/Cargo.lock index 71e90a8ef..72f5bad1b 100644 --- a/tests/Cargo.lock +++ b/tests/Cargo.lock @@ -354,7 +354,7 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hax-bounded-integers" -version = "0.3.2" +version = "0.3.4" dependencies = [ "duplicate", "hax-lib", @@ -363,7 +363,7 @@ dependencies = [ [[package]] name = "hax-lib" -version = "0.3.2" +version = "0.3.4" dependencies = [ "hax-lib-macros", "num-bigint", @@ -372,7 +372,7 @@ dependencies = [ [[package]] name = "hax-lib-macros" -version = "0.3.2" +version = "0.3.4" dependencies = [ "hax-lib-macros-types", "proc-macro-error2", @@ -383,7 +383,7 @@ dependencies = [ [[package]] name = "hax-lib-macros-types" -version = "0.3.2" +version = "0.3.4" dependencies = [ "proc-macro2", "quote", @@ -394,14 +394,14 @@ dependencies = [ [[package]] name = "hax-lib-protocol" -version = "0.3.2" +version = "0.3.4" dependencies = [ "libcrux", ] [[package]] name = "hax-lib-protocol-macros" -version = "0.3.2" +version = "0.3.4" dependencies = [ "proc-macro-error2", "proc-macro2",