Skip to content

Commit 51275e8

Browse files
committed
Elaborate ShallowInitBox too.
1 parent 4ddbb60 commit 51275e8

File tree

11 files changed

+256
-144
lines changed

11 files changed

+256
-144
lines changed

compiler/rustc_codegen_cranelift/src/base.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -829,13 +829,6 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
829829
fx.bcx.ins().nop();
830830
}
831831
}
832-
Rvalue::ShallowInitBox(ref operand, content_ty) => {
833-
let content_ty = fx.monomorphize(content_ty);
834-
let box_layout = fx.layout_of(Ty::new_box(fx.tcx, content_ty));
835-
let operand = codegen_operand(fx, operand);
836-
let operand = operand.load_scalar(fx);
837-
lval.write_cvalue(fx, CValue::by_val(operand, box_layout));
838-
}
839832
Rvalue::NullaryOp(ref null_op, ty) => {
840833
assert!(lval.layout().ty.is_sized(fx.tcx, fx.typing_env()));
841834
let layout = fx.layout_of(fx.monomorphize(ty));
@@ -924,6 +917,7 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
924917
lval.write_cvalue_transmute(fx, operand);
925918
}
926919
Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in codegen"),
920+
Rvalue::ShallowInitBox(..) => bug!("`ShallowInitBox` in codegen"),
927921
}
928922
}
929923
StatementKind::StorageLive(_)

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -724,22 +724,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
724724
}
725725
}
726726
}
727-
mir::Rvalue::ShallowInitBox(ref operand, content_ty) => {
728-
let operand = self.codegen_operand(bx, operand);
729-
let val = operand.immediate();
730-
731-
let content_ty = self.monomorphize(content_ty);
732-
let box_layout = bx.cx().layout_of(Ty::new_box(bx.tcx(), content_ty));
733-
734-
OperandRef { val: OperandValue::Immediate(val), layout: box_layout }
735-
}
736727
mir::Rvalue::WrapUnsafeBinder(ref operand, binder_ty) => {
737728
let operand = self.codegen_operand(bx, operand);
738729
let binder_ty = self.monomorphize(binder_ty);
739730
let layout = bx.cx().layout_of(binder_ty);
740731
OperandRef { val: operand.val, layout }
741732
}
742733
mir::Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in codegen"),
734+
mir::Rvalue::ShallowInitBox(..) => bug!("`ShallowInitBox` in codegen"),
743735
}
744736
}
745737

compiler/rustc_mir_transform/src/dataflow_const_prop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
480480
Rvalue::Discriminant(place) => state.get_discr(place.as_ref(), &self.map),
481481
Rvalue::Use(operand) => return self.handle_operand(operand, state),
482482
Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"),
483+
Rvalue::ShallowInitBox(..) => bug!("`ShallowInitBox` in runtime MIR"),
483484
Rvalue::Ref(..) | Rvalue::RawPtr(..) => {
484485
// We don't track such places.
485486
return ValueOrPlace::TOP;
@@ -489,7 +490,6 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
489490
| Rvalue::Cast(..)
490491
| Rvalue::BinaryOp(..)
491492
| Rvalue::Aggregate(..)
492-
| Rvalue::ShallowInitBox(..)
493493
| Rvalue::WrapUnsafeBinder(..) => {
494494
// No modification is possible through these r-values.
495495
return ValueOrPlace::TOP;

compiler/rustc_mir_transform/src/elaborate_box_derefs.rs

Lines changed: 83 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
11
//! This pass transforms derefs of Box into a deref of the pointer inside Box.
22
//!
33
//! Box is not actually a pointer so it is incorrect to dereference it directly.
4+
//!
5+
//! `ShallowInitBox` being a device for drop elaboration to understand deferred assignment to box
6+
//! contents, we do not need this any more on runtime MIR.
47
5-
use rustc_abi::FieldIdx;
6-
use rustc_hir::def_id::DefId;
8+
use rustc_abi::{FieldIdx, VariantIdx};
9+
use rustc_index::IndexVec;
710
use rustc_middle::mir::visit::MutVisitor;
811
use rustc_middle::mir::*;
912
use rustc_middle::span_bug;
10-
use rustc_middle::ty::{Ty, TyCtxt};
13+
use rustc_middle::ty::{self, Ty, TyCtxt};
1114

1215
use crate::patch::MirPatch;
1316

1417
/// Constructs the types used when accessing a Box's pointer
1518
fn build_ptr_tys<'tcx>(
1619
tcx: TyCtxt<'tcx>,
1720
pointee: Ty<'tcx>,
18-
unique_did: DefId,
19-
nonnull_did: DefId,
21+
unique_def: ty::AdtDef<'tcx>,
22+
nonnull_def: ty::AdtDef<'tcx>,
2023
) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) {
2124
let args = tcx.mk_args(&[pointee.into()]);
22-
let unique_ty = tcx.type_of(unique_did).instantiate(tcx, args);
23-
let nonnull_ty = tcx.type_of(nonnull_did).instantiate(tcx, args);
25+
let unique_ty = Ty::new_adt(tcx, unique_def, args);
26+
let nonnull_ty = Ty::new_adt(tcx, nonnull_def, args);
2427
let ptr_ty = Ty::new_imm_ptr(tcx, pointee);
2528

2629
(unique_ty, nonnull_ty, ptr_ty)
@@ -36,8 +39,8 @@ pub(super) fn build_projection<'tcx>(
3639

3740
struct ElaborateBoxDerefVisitor<'a, 'tcx> {
3841
tcx: TyCtxt<'tcx>,
39-
unique_did: DefId,
40-
nonnull_did: DefId,
42+
unique_def: ty::AdtDef<'tcx>,
43+
nonnull_def: ty::AdtDef<'tcx>,
4144
local_decls: &'a mut LocalDecls<'tcx>,
4245
patch: MirPatch<'tcx>,
4346
}
@@ -64,7 +67,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {
6467
let source_info = self.local_decls[place.local].source_info;
6568

6669
let (unique_ty, nonnull_ty, ptr_ty) =
67-
build_ptr_tys(tcx, boxed_ty, self.unique_did, self.nonnull_did);
70+
build_ptr_tys(tcx, boxed_ty, self.unique_def, self.nonnull_def);
6871

6972
let ptr_local = self.patch.new_temp(ptr_ty, source_info.span);
7073

@@ -86,6 +89,68 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {
8689

8790
self.super_place(place, context, location);
8891
}
92+
93+
fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, location: Location) {
94+
self.super_statement(stmt, location);
95+
96+
let tcx = self.tcx;
97+
let source_info = stmt.source_info;
98+
99+
if let StatementKind::Assign(box (_, ref mut rvalue)) = stmt.kind
100+
&& let Rvalue::ShallowInitBox(ref mut mutptr_to_u8, pointee) = *rvalue
101+
&& let ty::Adt(box_adt, box_args) = Ty::new_box(tcx, pointee).kind()
102+
{
103+
let args = tcx.mk_args(&[pointee.into()]);
104+
let (unique_ty, nonnull_ty, ptr_ty) =
105+
build_ptr_tys(tcx, pointee, self.unique_def, self.nonnull_def);
106+
let adt_kind = |def: ty::AdtDef<'tcx>, args| {
107+
Box::new(AggregateKind::Adt(def.did(), VariantIdx::ZERO, args, None, None))
108+
};
109+
let zst = |ty| {
110+
Operand::Constant(Box::new(ConstOperand {
111+
span: source_info.span,
112+
user_ty: None,
113+
const_: Const::zero_sized(ty),
114+
}))
115+
};
116+
117+
let constptr = self.patch.new_temp(ptr_ty, source_info.span);
118+
self.patch.add_assign(
119+
location,
120+
constptr.into(),
121+
Rvalue::Cast(CastKind::Transmute, mutptr_to_u8.clone(), ptr_ty),
122+
);
123+
124+
let nonnull = self.patch.new_temp(nonnull_ty, source_info.span);
125+
self.patch.add_assign(
126+
location,
127+
nonnull.into(),
128+
Rvalue::Aggregate(
129+
adt_kind(self.nonnull_def, args),
130+
IndexVec::from_raw(vec![Operand::Move(constptr.into())]),
131+
),
132+
);
133+
134+
let unique = self.patch.new_temp(unique_ty, source_info.span);
135+
let phantomdata_ty =
136+
self.unique_def.non_enum_variant().fields[FieldIdx::ONE].ty(tcx, args);
137+
self.patch.add_assign(
138+
location,
139+
unique.into(),
140+
Rvalue::Aggregate(
141+
adt_kind(self.unique_def, args),
142+
IndexVec::from_raw(vec![Operand::Move(nonnull.into()), zst(phantomdata_ty)]),
143+
),
144+
);
145+
146+
let global_alloc_ty =
147+
box_adt.non_enum_variant().fields[FieldIdx::ONE].ty(tcx, box_args);
148+
*rvalue = Rvalue::Aggregate(
149+
adt_kind(*box_adt, box_args),
150+
IndexVec::from_raw(vec![Operand::Move(unique.into()), zst(global_alloc_ty)]),
151+
);
152+
}
153+
}
89154
}
90155

91156
pub(super) struct ElaborateBoxDerefs;
@@ -97,18 +162,22 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
97162

98163
let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::ZERO].did;
99164

100-
let Some(nonnull_def) = tcx.type_of(unique_did).instantiate_identity().ty_adt_def() else {
165+
let Some(unique_def) = tcx.type_of(unique_did).instantiate_identity().ty_adt_def() else {
101166
span_bug!(tcx.def_span(unique_did), "expected Box to contain Unique")
102167
};
103168

104-
let nonnull_did = nonnull_def.non_enum_variant().fields[FieldIdx::ZERO].did;
169+
let nonnull_did = unique_def.non_enum_variant().fields[FieldIdx::ZERO].did;
170+
171+
let Some(nonnull_def) = tcx.type_of(nonnull_did).instantiate_identity().ty_adt_def() else {
172+
span_bug!(tcx.def_span(nonnull_did), "expected Unique to contain Nonnull")
173+
};
105174

106175
let patch = MirPatch::new(body);
107176

108177
let local_decls = &mut body.local_decls;
109178

110179
let mut visitor =
111-
ElaborateBoxDerefVisitor { tcx, unique_did, nonnull_did, local_decls, patch };
180+
ElaborateBoxDerefVisitor { tcx, unique_def, nonnull_def, local_decls, patch };
112181

113182
for (block, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
114183
visitor.visit_basic_block_data(block, data);
@@ -131,7 +200,7 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
131200
new_projections.get_or_insert_with(|| base.projection.to_vec());
132201

133202
let (unique_ty, nonnull_ty, ptr_ty) =
134-
build_ptr_tys(tcx, boxed_ty, unique_did, nonnull_did);
203+
build_ptr_tys(tcx, boxed_ty, unique_def, nonnull_def);
135204

136205
new_projections.extend_from_slice(&build_projection(unique_ty, nonnull_ty));
137206
// While we can't project into `NonNull<_>` in a basic block

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,8 +1073,10 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
10731073
}
10741074

10751075
// Unsupported values.
1076-
Rvalue::ThreadLocalRef(..) | Rvalue::ShallowInitBox(..) => return None,
1077-
Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"),
1076+
Rvalue::ThreadLocalRef(..) => return None,
1077+
Rvalue::CopyForDeref(_) | Rvalue::ShallowInitBox(..) => {
1078+
bug!("forbidden in runtime MIR: {rvalue:?}")
1079+
}
10781080
};
10791081
let ty = rvalue.ty(self.local_decls, self.tcx);
10801082
Some(self.insert(ty, value))

compiler/rustc_mir_transform/src/validate.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
656656
) {
657657
match elem {
658658
ProjectionElem::Deref
659-
if self.body.phase >= MirPhase::Runtime(RuntimePhase::PostCleanup) =>
659+
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) =>
660660
{
661661
let base_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty;
662662

@@ -1047,7 +1047,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
10471047
assert!(!adt_def.is_union());
10481048
let variant = &adt_def.variants()[idx];
10491049
if variant.fields.len() != fields.len() {
1050-
self.fail(location, "adt has the wrong number of initialized fields");
1050+
self.fail(location, format!(
1051+
"adt {def_id:?} has the wrong number of initialized fields, expected {}, found {}",
1052+
fields.len(),
1053+
variant.fields.len(),
1054+
));
10511055
}
10521056
for (src, dest) in std::iter::zip(fields, &variant.fields) {
10531057
let dest_ty = self
@@ -1250,6 +1254,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
12501254
}
12511255
}
12521256
Rvalue::ShallowInitBox(operand, _) => {
1257+
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
1258+
self.fail(location, format!("ShallowInitBox after ElaborateBoxDerefs"))
1259+
}
1260+
12531261
let a = operand.ty(&self.body.local_decls, self.tcx);
12541262
check_kinds!(a, "Cannot shallow init type {:?}", ty::RawPtr(..));
12551263
}

tests/mir-opt/box_expr.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
// EMIT_MIR box_expr.main.ElaborateDrops.diff
77
fn main() {
88
// CHECK-LABEL: fn main(
9-
// CHECK: [[box:_.*]] = ShallowInitBox(
9+
// CHECK: [[ptr:_.*]] = move {{_.*}} as *const S (Transmute);
10+
// CHECK: [[nonnull:_.*]] = NonNull::<S> { pointer: move [[ptr]] };
11+
// CHECK: [[unique:_.*]] = Unique::<S> { pointer: move [[nonnull]], _marker: const PhantomData::<S> };
12+
// CHECK: [[box:_.*]] = Box::<S>(move [[unique]], const std::alloc::Global);
1013
// CHECK: [[ptr:_.*]] = copy (([[box]].0: std::ptr::Unique<S>).0: std::ptr::NonNull<S>) as *const S (Transmute);
1114
// CHECK: (*[[ptr]]) = S::new() -> [return: [[ret:bb.*]], unwind: [[unwind:bb.*]]];
1215
// CHECK: [[ret]]: {

tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
let mut _6: *mut u8;
1212
let mut _7: std::boxed::Box<i32>;
1313
let mut _8: *const i32;
14-
let mut _9: *const i32;
14+
let mut _9: std::ptr::NonNull<i32>;
15+
let mut _10: std::ptr::Unique<i32>;
16+
let mut _11: *const i32;
17+
let mut _12: *const i32;
1518
scope 1 {
1619
debug x => _1;
1720
}
@@ -31,13 +34,21 @@
3134

3235
bb1: {
3336
StorageLive(_7);
34-
_7 = ShallowInitBox(move _6, i32);
35-
_8 = copy ((_7.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
36-
(*_8) = const 42_i32;
37+
- _8 = move _6 as *const i32 (Transmute);
38+
- _9 = NonNull::<i32> { pointer: move _8 };
39+
- _10 = Unique::<i32> { pointer: move _9, _marker: const PhantomData::<i32> };
40+
+ _8 = copy _6 as *const i32 (PtrToPtr);
41+
+ _9 = NonNull::<i32> { pointer: copy _8 };
42+
+ _10 = Unique::<i32> { pointer: copy _9, _marker: const PhantomData::<i32> };
43+
_7 = Box::<i32>(move _10, const std::alloc::Global);
44+
- _11 = copy ((_7.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
45+
- (*_11) = const 42_i32;
46+
+ _11 = copy _8;
47+
+ (*_8) = const 42_i32;
3748
_3 = move _7;
3849
StorageDead(_7);
39-
_9 = copy ((_3.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
40-
_2 = copy (*_9);
50+
_12 = copy ((_3.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
51+
_2 = copy (*_12);
4152
- _1 = Add(move _2, const 0_i32);
4253
- StorageDead(_2);
4354
+ _1 = copy _2;

tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
let mut _6: *mut u8;
1212
let mut _7: std::boxed::Box<i32>;
1313
let mut _8: *const i32;
14-
let mut _9: *const i32;
14+
let mut _9: std::ptr::NonNull<i32>;
15+
let mut _10: std::ptr::Unique<i32>;
16+
let mut _11: *const i32;
17+
let mut _12: *const i32;
1518
scope 1 {
1619
debug x => _1;
1720
}
@@ -31,13 +34,21 @@
3134

3235
bb1: {
3336
StorageLive(_7);
34-
_7 = ShallowInitBox(move _6, i32);
35-
_8 = copy ((_7.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
36-
(*_8) = const 42_i32;
37+
- _8 = move _6 as *const i32 (Transmute);
38+
- _9 = NonNull::<i32> { pointer: move _8 };
39+
- _10 = Unique::<i32> { pointer: move _9, _marker: const PhantomData::<i32> };
40+
+ _8 = copy _6 as *const i32 (PtrToPtr);
41+
+ _9 = NonNull::<i32> { pointer: copy _8 };
42+
+ _10 = Unique::<i32> { pointer: copy _9, _marker: const PhantomData::<i32> };
43+
_7 = Box::<i32>(move _10, const std::alloc::Global);
44+
- _11 = copy ((_7.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
45+
- (*_11) = const 42_i32;
46+
+ _11 = copy _8;
47+
+ (*_8) = const 42_i32;
3748
_3 = move _7;
3849
StorageDead(_7);
39-
_9 = copy ((_3.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
40-
_2 = copy (*_9);
50+
_12 = copy ((_3.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
51+
_2 = copy (*_12);
4152
- _1 = Add(move _2, const 0_i32);
4253
- StorageDead(_2);
4354
+ _1 = copy _2;

0 commit comments

Comments
 (0)