From 0df1764e60e4ca63d5aeb4c78e1f4b3bf8ff3709 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 7 Feb 2026 19:11:38 +0100 Subject: [PATCH] add helper to project to a field of a place --- compiler/rustc_middle/src/mir/statement.rs | 16 ++++++++++++++ .../rustc_mir_build/src/builder/expr/into.rs | 22 +++++-------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 973ceccc67f9..b1cb89bd3713 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -432,6 +432,22 @@ impl<'tcx> Place<'tcx> { self.as_ref().project_deeper(more_projections, tcx) } + /// Return a place that projects to a field of the current place. + /// + /// The type of the current place must be an ADT. + pub fn project_to_field( + self, + idx: FieldIdx, + local_decls: &impl HasLocalDecls<'tcx>, + tcx: TyCtxt<'tcx>, + ) -> Self { + let ty = self.ty(local_decls, tcx).ty; + let ty::Adt(adt, args) = ty.kind() else { panic!("projecting to field of non-ADT {ty}") }; + let field = &adt.non_enum_variant().fields[idx]; + let field_ty = field.ty(tcx, args); + self.project_deeper(&[ProjectionElem::Field(idx, field_ty)], tcx) + } + pub fn ty_from( local: Local, projection: &[PlaceElem<'tcx>], diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 34fd9fc7ac63..e8427b5d6e1e 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -409,7 +409,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // cause the borrow checker to enforce that `val` lives sufficiently // long to be stored in `b`. The above lowering does this; anything that // involves a `*const T` or a `NonNull` does not as those are covariant. - let tcx = this.tcx; // Extract the operands, compile `b`. let [b, val] = **args else { @@ -419,28 +418,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { else { span_bug!(expr_span, "invalid init_box_via_move call") }; - - // Helper to project to a field of an ADT. - let place_project_field = |place: Place<'tcx>, idx: FieldIdx| { - let ty = place.ty(&this.local_decls, tcx).ty; - let ty::Adt(adt, args) = ty.kind() else { - panic!("projecting to field of non-ADT {ty}") - }; - let field = &adt.non_enum_variant().fields[idx]; - let field_ty = field.ty(tcx, args); - place.project_deeper(&[ProjectionElem::Field(idx, field_ty)], tcx) - }; + let tcx = this.tcx; + let decls = &this.local_decls; // `b` is a `Box>`. let place = b.project_deeper(&[ProjectionElem::Deref], tcx); // Current type: `MaybeUninit`. Field #1 is `ManuallyDrop`. - let place = place_project_field(place, FieldIdx::from_u32(1)); + let place = place.project_to_field(FieldIdx::from_u32(1), decls, tcx); // Current type: `ManuallyDrop`. Field #0 is `MaybeDangling`. - let place = place_project_field(place, FieldIdx::ZERO); + let place = place.project_to_field(FieldIdx::ZERO, decls, tcx); // Current type: `MaybeDangling`. Field #0 is `T`. - let place = place_project_field(place, FieldIdx::ZERO); + let place = place.project_to_field(FieldIdx::ZERO, decls, tcx); // Sanity check. - assert_eq!(place.ty(&this.local_decls, tcx).ty, generic_args.type_at(0)); + assert_eq!(place.ty(decls, tcx).ty, generic_args.type_at(0)); // Store `val` into place. unpack!(block = this.expr_into_dest(place, block, val));