Skip to content

Commit 0df1764

Browse files
committed
add helper to project to a field of a place
1 parent e5ed864 commit 0df1764

2 files changed

Lines changed: 22 additions & 16 deletions

File tree

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,22 @@ impl<'tcx> Place<'tcx> {
432432
self.as_ref().project_deeper(more_projections, tcx)
433433
}
434434

435+
/// Return a place that projects to a field of the current place.
436+
///
437+
/// The type of the current place must be an ADT.
438+
pub fn project_to_field(
439+
self,
440+
idx: FieldIdx,
441+
local_decls: &impl HasLocalDecls<'tcx>,
442+
tcx: TyCtxt<'tcx>,
443+
) -> Self {
444+
let ty = self.ty(local_decls, tcx).ty;
445+
let ty::Adt(adt, args) = ty.kind() else { panic!("projecting to field of non-ADT {ty}") };
446+
let field = &adt.non_enum_variant().fields[idx];
447+
let field_ty = field.ty(tcx, args);
448+
self.project_deeper(&[ProjectionElem::Field(idx, field_ty)], tcx)
449+
}
450+
435451
pub fn ty_from<D>(
436452
local: Local,
437453
projection: &[PlaceElem<'tcx>],

compiler/rustc_mir_build/src/builder/expr/into.rs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
409409
// cause the borrow checker to enforce that `val` lives sufficiently
410410
// long to be stored in `b`. The above lowering does this; anything that
411411
// involves a `*const T` or a `NonNull<T>` does not as those are covariant.
412-
let tcx = this.tcx;
413412

414413
// Extract the operands, compile `b`.
415414
let [b, val] = **args else {
@@ -419,28 +418,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
419418
else {
420419
span_bug!(expr_span, "invalid init_box_via_move call")
421420
};
422-
423-
// Helper to project to a field of an ADT.
424-
let place_project_field = |place: Place<'tcx>, idx: FieldIdx| {
425-
let ty = place.ty(&this.local_decls, tcx).ty;
426-
let ty::Adt(adt, args) = ty.kind() else {
427-
panic!("projecting to field of non-ADT {ty}")
428-
};
429-
let field = &adt.non_enum_variant().fields[idx];
430-
let field_ty = field.ty(tcx, args);
431-
place.project_deeper(&[ProjectionElem::Field(idx, field_ty)], tcx)
432-
};
421+
let tcx = this.tcx;
422+
let decls = &this.local_decls;
433423

434424
// `b` is a `Box<MaybeUninit<T>>`.
435425
let place = b.project_deeper(&[ProjectionElem::Deref], tcx);
436426
// Current type: `MaybeUninit<T>`. Field #1 is `ManuallyDrop<T>`.
437-
let place = place_project_field(place, FieldIdx::from_u32(1));
427+
let place = place.project_to_field(FieldIdx::from_u32(1), decls, tcx);
438428
// Current type: `ManuallyDrop<T>`. Field #0 is `MaybeDangling<T>`.
439-
let place = place_project_field(place, FieldIdx::ZERO);
429+
let place = place.project_to_field(FieldIdx::ZERO, decls, tcx);
440430
// Current type: `MaybeDangling<T>`. Field #0 is `T`.
441-
let place = place_project_field(place, FieldIdx::ZERO);
431+
let place = place.project_to_field(FieldIdx::ZERO, decls, tcx);
442432
// Sanity check.
443-
assert_eq!(place.ty(&this.local_decls, tcx).ty, generic_args.type_at(0));
433+
assert_eq!(place.ty(decls, tcx).ty, generic_args.type_at(0));
444434

445435
// Store `val` into place.
446436
unpack!(block = this.expr_into_dest(place, block, val));

0 commit comments

Comments
 (0)