Skip to content

Commit f069d6b

Browse files
committed
Emit either mono item of Drop::drop or Drop::pin_drop depending on which was implemented
1 parent 64a965e commit f069d6b

10 files changed

Lines changed: 90 additions & 21 deletions

File tree

compiler/rustc_mir_transform/src/elaborate_drop.rs

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_middle::ty::adjustment::PointerCoercion;
99
use rustc_middle::ty::util::IntTypeExt;
1010
use rustc_middle::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt, Unnormalized};
1111
use rustc_middle::{bug, span_bug, traits};
12+
use rustc_span::symbol::sym;
1213
use rustc_span::{DUMMY_SP, Spanned, dummy_spanned};
1314
use tracing::{debug, instrument};
1415

@@ -999,22 +1000,51 @@ where
9991000
debug!("destructor_call_block_sync({:?}, {:?})", self, succ);
10001001
let tcx = self.tcx();
10011002
let drop_trait = tcx.require_lang_item(LangItem::Drop, DUMMY_SP);
1002-
let drop_fn = tcx.associated_item_def_ids(drop_trait)[0];
1003+
let mut drop_fn = tcx.associated_item_def_ids(drop_trait)[0];
10031004
let ty = self.place_ty(self.place);
10041005

10051006
let ref_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty);
10061007
let ref_place = self.new_temp(ref_ty);
10071008
let unit_temp = Place::from(self.new_temp(tcx.types.unit));
10081009

1009-
let result = BasicBlockData::new_stmts(
1010-
vec![self.assign(
1011-
Place::from(ref_place),
1012-
Rvalue::Ref(
1013-
tcx.lifetimes.re_erased,
1014-
BorrowKind::Mut { kind: MutBorrowKind::Default },
1015-
self.place,
1010+
let mut arg_place = ref_place;
1011+
1012+
let mut stmts = vec![self.assign(
1013+
Place::from(ref_place),
1014+
Rvalue::Ref(
1015+
tcx.lifetimes.re_erased,
1016+
BorrowKind::Mut { kind: MutBorrowKind::Default },
1017+
self.place,
1018+
),
1019+
)];
1020+
1021+
// When the type implements `Drop::pin_drop`, we call it directly instead of `Drop::drop`.
1022+
if let Some(adt) = ty.ty_adt_def()
1023+
&& let Some(dtor) = adt.destructor(tcx)
1024+
&& tcx.item_name(dtor.did) == sym::pin_drop
1025+
{
1026+
debug!("call `pin_drop` for {adt:?}");
1027+
let pin_ref_ty = Ty::new_pinned_ref(tcx, tcx.lifetimes.re_erased, ty, Mutability::Mut);
1028+
let pin_ref_place = self.new_temp(pin_ref_ty);
1029+
stmts.push(self.assign(
1030+
Place::from(pin_ref_place),
1031+
Rvalue::Aggregate(
1032+
Box::new(AggregateKind::Adt(
1033+
tcx.require_lang_item(LangItem::Pin, DUMMY_SP),
1034+
VariantIdx::ZERO,
1035+
tcx.mk_args(&[ref_ty.into()]),
1036+
None,
1037+
None,
1038+
)),
1039+
[Operand::Move(Place::from(ref_place))].into(),
10161040
),
1017-
)],
1041+
));
1042+
drop_fn = tcx.associated_item_def_ids(drop_trait)[1];
1043+
arg_place = pin_ref_place;
1044+
}
1045+
1046+
let result = BasicBlockData::new_stmts(
1047+
stmts,
10181048
Some(Terminator {
10191049
kind: TerminatorKind::Call {
10201050
func: Operand::function_handle(
@@ -1023,7 +1053,7 @@ where
10231053
[ty.into()],
10241054
self.source_info.span,
10251055
),
1026-
args: [Spanned { node: Operand::Move(Place::from(ref_place)), span: DUMMY_SP }]
1056+
args: [Spanned { node: Operand::Move(Place::from(arg_place)), span: DUMMY_SP }]
10271057
.into(),
10281058
destination: unit_temp,
10291059
target: Some(succ),

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,15 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) ->
10621062
tcx.dcx().delayed_bug("attempt to codegen `#[rustc_force_inline]` item");
10631063
}
10641064

1065+
// It is not possible to manually call `Drop::drop` and `Drop::pin_drop`, so we can
1066+
// skip codegen for mentioned associated items of the `Drop` trait, and only codegen
1067+
// `drop` or `pin_drop` depending on which was implemented.
1068+
if let Some(trait_id) = tcx.trait_of_assoc(def_id)
1069+
&& tcx.is_lang_item(trait_id, LangItem::Drop)
1070+
{
1071+
return false;
1072+
}
1073+
10651074
if def_id.is_local() {
10661075
// Local items cannot be referred to locally without monomorphizing them locally.
10671076
return true;

tests/codegen-units/item-collection/drop-glue-eager.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ struct StructWithDrop {
1010

1111
impl Drop for StructWithDrop {
1212
//~ MONO_ITEM fn <StructWithDrop as std::ops::Drop>::drop
13-
//~ MONO_ITEM fn <StructWithDrop as std::ops::Drop>::pin_drop
1413
fn drop(&mut self) {}
1514
}
1615

@@ -25,7 +24,6 @@ enum EnumWithDrop {
2524

2625
impl Drop for EnumWithDrop {
2726
//~ MONO_ITEM fn <EnumWithDrop as std::ops::Drop>::drop
28-
//~ MONO_ITEM fn <EnumWithDrop as std::ops::Drop>::pin_drop
2927
fn drop(&mut self) {}
3028
}
3129

@@ -36,7 +34,6 @@ enum EnumNoDrop {
3634
// We should be able to monomorphize drops for struct with lifetimes.
3735
impl<'a> Drop for StructWithDropAndLt<'a> {
3836
//~ MONO_ITEM fn <StructWithDropAndLt<'_> as std::ops::Drop>::drop
39-
//~ MONO_ITEM fn <StructWithDropAndLt<'_> as std::ops::Drop>::pin_drop
4037
fn drop(&mut self) {}
4138
}
4239

@@ -55,6 +52,5 @@ struct StructWithLtAndPredicate<'a: 'a> {
5552
// We should be able to monomorphize drops for struct with lifetimes.
5653
impl<'a> Drop for StructWithLtAndPredicate<'a> {
5754
//~ MONO_ITEM fn <StructWithLtAndPredicate<'_> as std::ops::Drop>::drop
58-
//~ MONO_ITEM fn <StructWithLtAndPredicate<'_> as std::ops::Drop>::pin_drop
5955
fn drop(&mut self) {}
6056
}

tests/codegen-units/item-collection/drop_in_place_intrinsic.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ struct StructWithDtor(u32);
99

1010
impl Drop for StructWithDtor {
1111
//~ MONO_ITEM fn <StructWithDtor as std::ops::Drop>::drop
12-
//~ MONO_ITEM fn <StructWithDtor as std::ops::Drop>::pin_drop
1312
fn drop(&mut self) {}
1413
}
1514
//~ MONO_ITEM fn start

tests/codegen-units/item-collection/generic-drop-glue.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ struct NonGenericWithDrop(#[allow(dead_code)] i32);
3939

4040
impl Drop for NonGenericWithDrop {
4141
//~ MONO_ITEM fn <NonGenericWithDrop as std::ops::Drop>::drop
42-
//~ MONO_ITEM fn <NonGenericWithDrop as std::ops::Drop>::pin_drop
4342
fn drop(&mut self) {}
4443
}
4544

tests/codegen-units/item-collection/non-generic-closures.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,5 @@ struct PresentDrop;
7474

7575
impl Drop for PresentDrop {
7676
//~ MONO_ITEM fn <PresentDrop as std::ops::Drop>::drop @@ non_generic_closures-cgu.0[External]
77-
//~ MONO_ITEM fn <PresentDrop as std::ops::Drop>::pin_drop @@ non_generic_closures-cgu.0[External]
7877
fn drop(&mut self) {}
7978
}

tests/codegen-units/item-collection/non-generic-drop-glue.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ struct StructWithDrop {
1111

1212
impl Drop for StructWithDrop {
1313
//~ MONO_ITEM fn <StructWithDrop as std::ops::Drop>::drop
14-
//~ MONO_ITEM fn <StructWithDrop as std::ops::Drop>::pin_drop
1514
fn drop(&mut self) {}
1615
}
1716

@@ -26,7 +25,6 @@ enum EnumWithDrop {
2625

2726
impl Drop for EnumWithDrop {
2827
//~ MONO_ITEM fn <EnumWithDrop as std::ops::Drop>::drop
29-
//~ MONO_ITEM fn <EnumWithDrop as std::ops::Drop>::pin_drop
3028
fn drop(&mut self) {}
3129
}
3230

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#![feature(pin_ergonomics)]
2+
// Ensure that we emit either `Drop::drop` or `Drop::pin_drop` for types that implement `Drop`.
3+
4+
//@ compile-flags:-Clink-dead-code
5+
//@ compile-flags:--crate-type=lib
6+
//@ rustc-env:MONO_TEST=1
7+
8+
//~ MONO_ITEM fn std::ptr::drop_glue::<StructWithDrop> - shim(Some(StructWithDrop))
9+
struct StructWithDrop {
10+
x: i32,
11+
}
12+
13+
impl Drop for StructWithDrop {
14+
//~ MONO_ITEM fn <StructWithDrop as std::ops::Drop>::drop
15+
fn drop(&mut self) {}
16+
}
17+
18+
struct StructNoDrop {
19+
x: i32,
20+
}
21+
22+
//~ MONO_ITEM fn std::ptr::drop_glue::<StructWithPinDrop> - shim(Some(StructWithPinDrop))
23+
struct StructWithPinDrop {
24+
x: i32,
25+
}
26+
27+
impl Drop for StructWithPinDrop {
28+
//~ MONO_ITEM fn <StructWithPinDrop as std::ops::Drop>::pin_drop
29+
fn pin_drop(&pin mut self) {}
30+
}
31+
32+
//~ MONO_ITEM fn std::ptr::drop_glue::<StructPinV2WithPinDrop> - shim(Some(StructPinV2WithPinDrop))
33+
#[pin_v2]
34+
struct StructPinV2WithPinDrop {
35+
x: i32,
36+
}
37+
38+
impl Drop for StructPinV2WithPinDrop {
39+
//~ MONO_ITEM fn <StructPinV2WithPinDrop as std::ops::Drop>::pin_drop
40+
fn pin_drop(&pin mut self) {}
41+
}

tests/codegen-units/item-collection/transitive-drop-glue.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ struct Leaf;
1313

1414
impl Drop for Leaf {
1515
//~ MONO_ITEM fn <Leaf as std::ops::Drop>::drop
16-
//~ MONO_ITEM fn <Leaf as std::ops::Drop>::pin_drop
1716
fn drop(&mut self) {}
1817
}
1918

tests/codegen-units/item-collection/tuple-drop-glue.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ struct Dropped;
99

1010
impl Drop for Dropped {
1111
//~ MONO_ITEM fn <Dropped as std::ops::Drop>::drop
12-
//~ MONO_ITEM fn <Dropped as std::ops::Drop>::pin_drop
1312
fn drop(&mut self) {}
1413
}
1514

0 commit comments

Comments
 (0)