Skip to content

Commit ec33dfc

Browse files
committed
Auto merge of #155184 - scottmcm:intercept-array-drop-shim, r=<try>
Have arrays' `drop_glue` just unsize and call the slice version
2 parents 4a997ee + b0020c9 commit ec33dfc

3 files changed

Lines changed: 112 additions & 53 deletions

File tree

compiler/rustc_mir_transform/src/shim.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,16 +317,56 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
317317
let block = |blocks: &mut IndexVec<_, _>, kind| {
318318
blocks.push(BasicBlockData::new(Some(Terminator { source_info, kind }), false))
319319
};
320-
block(&mut blocks, TerminatorKind::Goto { target: return_block });
320+
if ty.is_some() {
321+
block(&mut blocks, TerminatorKind::Goto { target: return_block });
322+
}
321323
block(&mut blocks, TerminatorKind::Return);
322324

323325
let source = MirSource::from_instance(ty::InstanceKind::DropGlue(def_id, ty));
324326
let mut body =
325327
new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
326328

329+
let Some(ty) = ty else {
330+
return body;
331+
};
332+
327333
let dropee_ptr = Place::from(Local::arg(0));
328334

329-
if ty.is_some() {
335+
if let ty::Array(ety, _len) = *ty.kind() {
336+
// Don't write out the elaboration for each array type.
337+
// Instead, just delegate to the slice version.
338+
let slice_ty = Ty::new_slice(tcx, ety);
339+
let mut_slice_ty = Ty::new_ref(tcx, tcx.lifetimes.re_erased, slice_ty, ty::Mutability::Mut);
340+
let erased_local = body.local_decls.push(LocalDecl::new(mut_slice_ty, span));
341+
342+
let start = &mut body.basic_blocks_mut()[START_BLOCK];
343+
start.statements.push(Statement::new(
344+
source_info,
345+
StatementKind::Assign(Box::new((
346+
Place::from(erased_local),
347+
Rvalue::Cast(
348+
CastKind::PointerCoercion(
349+
ty::adjustment::PointerCoercion::Unsize,
350+
CoercionSource::Implicit,
351+
),
352+
Operand::Move(dropee_ptr),
353+
mut_slice_ty,
354+
),
355+
))),
356+
));
357+
start.terminator = Some(Terminator {
358+
source_info,
359+
kind: TerminatorKind::Call {
360+
func: Operand::function_handle(tcx, def_id, [ty::GenericArg::from(slice_ty)], span),
361+
args: Box::new([Spanned { span, node: Operand::Move(Place::from(erased_local)) }]),
362+
destination: Place::from(RETURN_PLACE),
363+
target: Some(return_block),
364+
unwind: UnwindAction::Continue,
365+
call_source: CallSource::Misc,
366+
fn_span: span,
367+
},
368+
});
369+
} else {
330370
let patch = {
331371
let typing_env = ty::TypingEnv::post_analysis(tcx, def_id);
332372
let mut elaborator = DropShimElaborator {
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//@ revisions: RAW OPT
2+
//@ compile-flags: -C opt-level=z -C panic=abort
3+
//@[RAW] compile-flags: -C no-prepopulate-passes -Z inline-mir
4+
5+
#![crate_type = "lib"]
6+
7+
// Ensure all the different array drop_glue functions just delegate to the slice one,
8+
// rather than emitting two loops in each of the three.
9+
10+
// When this test was first written, the array drop glues came out in the
11+
// seemingly-arbitrary order of 42, then 7, then 13, so to avoid potential
12+
// fragility from that changing we don't check any particular order.
13+
14+
// RAW: ; core::ptr::drop_glue::<[array_drop_glue::NeedsDrop; [[N:7|13|42]]]>
15+
// RAW-NOT: inlinehint
16+
// RAW: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop]>
17+
// RAW-NEXT: noundef [[N]])
18+
// RAW: }
19+
20+
// RAW: ; core::ptr::drop_glue::<[array_drop_glue::NeedsDrop; [[N:7|13|42]]]>
21+
// RAW-NOT: inlinehint
22+
// RAW: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop]>
23+
// RAW-NEXT: noundef [[N]])
24+
// RAW: }
25+
26+
// RAW: ; core::ptr::drop_glue::<[array_drop_glue::NeedsDrop; [[N:7|13|42]]]>
27+
// RAW-NOT: inlinehint
28+
// RAW: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop]>
29+
// RAW-NEXT: noundef [[N]])
30+
// RAW: }
31+
32+
// CHECK-LABEL: ; core::ptr::drop_glue::<[array_drop_glue::NeedsDrop]>
33+
// CHECK-NOT: inlinehint
34+
// OPT: add nuw nsw {{.+}} 1
35+
// CHECK: }
36+
37+
#[no_mangle]
38+
// CHECK-LABEL: @drop_arrays
39+
pub fn drop_arrays(x: [NeedsDrop; 7], y: [NeedsDrop; 13], z: [NeedsDrop; 42]) {
40+
// I don't remember the parameter drop order, so write out the order the test expects.
41+
42+
// RAW: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop; 7]>
43+
// OPT: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop]>
44+
// OPT-NEXT: noundef 7)
45+
drop(x);
46+
// RAW: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop; 13]>
47+
// OPT: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop]>
48+
// OPT-NEXT: noundef 13)
49+
drop(y);
50+
// RAW: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop; 42]>
51+
// OPT: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop]>
52+
// OPT-NEXT: noundef 42)
53+
drop(z);
54+
}
55+
56+
struct NeedsDrop(u32);
57+
58+
impl Drop for NeedsDrop {
59+
#[inline]
60+
fn drop(&mut self) {
61+
do_the_drop(self);
62+
}
63+
}
64+
65+
unsafe extern "Rust" {
66+
safe fn do_the_drop(_: &mut NeedsDrop);
67+
}

tests/mir-opt/slice_drop_shim.core.ptr-drop_glue.[String;42].AddMovesForPackedDrops.before.mir

Lines changed: 3 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,14 @@
22

33
fn std::ptr::drop_glue(_1: &mut [String; 42]) -> () {
44
let mut _0: ();
5-
let mut _2: *mut [std::string::String; 42];
6-
let mut _3: *mut [std::string::String];
7-
let mut _4: usize;
8-
let mut _5: usize;
9-
let mut _6: *mut std::string::String;
10-
let mut _7: bool;
11-
let mut _8: *mut std::string::String;
12-
let mut _9: bool;
5+
let mut _2: &mut [std::string::String];
136

147
bb0: {
15-
goto -> bb9;
8+
_2 = move _1 as &mut [std::string::String] (PointerCoercion(Unsize, Implicit));
9+
_0 = std::ptr::drop_glue::<[String]>(move _2) -> [return: bb1, unwind continue];
1610
}
1711

1812
bb1: {
1913
return;
2014
}
21-
22-
bb2 (cleanup): {
23-
resume;
24-
}
25-
26-
bb3 (cleanup): {
27-
_6 = &raw mut (*_3)[_5];
28-
_5 = Add(move _5, const 1_usize);
29-
drop((*_6)) -> [return: bb4, unwind terminate(cleanup)];
30-
}
31-
32-
bb4 (cleanup): {
33-
_7 = Eq(copy _5, copy _4);
34-
switchInt(move _7) -> [0: bb3, otherwise: bb2];
35-
}
36-
37-
bb5: {
38-
_8 = &raw mut (*_3)[_5];
39-
_5 = Add(move _5, const 1_usize);
40-
drop((*_8)) -> [return: bb6, unwind: bb4];
41-
}
42-
43-
bb6: {
44-
_9 = Eq(copy _5, copy _4);
45-
switchInt(move _9) -> [0: bb5, otherwise: bb1];
46-
}
47-
48-
bb7: {
49-
_4 = PtrMetadata(copy _3);
50-
_5 = const 0_usize;
51-
goto -> bb6;
52-
}
53-
54-
bb8: {
55-
goto -> bb7;
56-
}
57-
58-
bb9: {
59-
_2 = &raw mut (*_1);
60-
_3 = move _2 as *mut [std::string::String] (PointerCoercion(Unsize, Implicit));
61-
goto -> bb8;
62-
}
6315
}

0 commit comments

Comments
 (0)