From 043bac9e73b3814cfc7bcb2f03e4dd6404f5630a Mon Sep 17 00:00:00 2001 From: Frank King Date: Tue, 12 May 2026 16:08:55 +0800 Subject: [PATCH] Emit either mono item of `Drop::drop` or `Drop::pin_drop` depending on which was implemented --- .../rustc_mir_transform/src/elaborate_drop.rs | 50 +++++++++++++++---- compiler/rustc_monomorphize/src/collector.rs | 9 ++++ .../item-collection/drop-glue-eager.rs | 4 -- .../drop_in_place_intrinsic.rs | 1 - .../item-collection/generic-drop-glue.rs | 1 - .../item-collection/non-generic-closures.rs | 1 - .../item-collection/non-generic-drop-glue.rs | 2 - .../codegen-units/item-collection/pin-drop.rs | 41 +++++++++++++++ .../item-collection/transitive-drop-glue.rs | 1 - .../item-collection/tuple-drop-glue.rs | 1 - 10 files changed, 90 insertions(+), 21 deletions(-) create mode 100644 tests/codegen-units/item-collection/pin-drop.rs diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index c835ff7dbe070..d745e9874c6cc 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -9,6 +9,7 @@ use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt}; use rustc_middle::{bug, span_bug, traits}; +use rustc_span::symbol::sym; use rustc_span::{DUMMY_SP, Spanned, dummy_spanned}; use tracing::{debug, instrument}; @@ -973,26 +974,55 @@ where fn destructor_call_block_sync(&mut self, succ: BasicBlock, unwind: Unwind) -> BasicBlock { let tcx = self.tcx(); let drop_trait = tcx.require_lang_item(LangItem::Drop, DUMMY_SP); - let drop_fn = tcx.associated_item_def_ids(drop_trait)[0]; + let mut drop_fn = tcx.associated_item_def_ids(drop_trait)[0]; let ty = self.place_ty(self.place); let ref_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty); let ref_place = self.new_temp(ref_ty); let unit_temp = Place::from(self.new_temp(tcx.types.unit)); + let mut arg_place = ref_place; + + let mut stmts = vec![self.assign( + Place::from(ref_place), + Rvalue::Ref( + tcx.lifetimes.re_erased, + BorrowKind::Mut { kind: MutBorrowKind::Default }, + self.place, + ), + )]; + + // When the type implements `Drop::pin_drop`, we call it directly instead of `Drop::drop`. + if let Some(adt) = ty.ty_adt_def() + && let Some(dtor) = adt.destructor(tcx) + && tcx.item_name(dtor.did) == sym::pin_drop + { + debug!("call `pin_drop` for {adt:?}"); + let pin_ref_ty = Ty::new_pinned_ref(tcx, tcx.lifetimes.re_erased, ty, Mutability::Mut); + let pin_ref_place = self.new_temp(pin_ref_ty); + stmts.push(self.assign( + Place::from(pin_ref_place), + Rvalue::Aggregate( + Box::new(AggregateKind::Adt( + tcx.require_lang_item(LangItem::Pin, DUMMY_SP), + VariantIdx::ZERO, + tcx.mk_args(&[ref_ty.into()]), + None, + None, + )), + [Operand::Move(Place::from(ref_place))].into(), + ), + )); + drop_fn = tcx.associated_item_def_ids(drop_trait)[1]; + arg_place = pin_ref_place; + } + self.new_block_with_statements( unwind, - vec![self.assign( - Place::from(ref_place), - Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { kind: MutBorrowKind::Default }, - self.place, - ), - )], + stmts, TerminatorKind::Call { func: Operand::function_handle(tcx, drop_fn, [ty.into()], self.source_info.span), - args: [Spanned { node: Operand::Move(Place::from(ref_place)), span: DUMMY_SP }] + args: [Spanned { node: Operand::Move(Place::from(arg_place)), span: DUMMY_SP }] .into(), destination: unit_temp, target: Some(succ), diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 9ddd33678c341..d9ce962d34a37 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1062,6 +1062,15 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> tcx.dcx().delayed_bug("attempt to codegen `#[rustc_force_inline]` item"); } + // It is not possible to manually call `Drop::drop` and `Drop::pin_drop`, so we can + // skip codegen for mentioned associated items of the `Drop` trait, and only codegen + // `drop` or `pin_drop` depending on which was implemented. + if let Some(trait_id) = tcx.trait_of_assoc(def_id) + && tcx.is_lang_item(trait_id, LangItem::Drop) + { + return false; + } + if def_id.is_local() { // Local items cannot be referred to locally without monomorphizing them locally. return true; diff --git a/tests/codegen-units/item-collection/drop-glue-eager.rs b/tests/codegen-units/item-collection/drop-glue-eager.rs index ae9536887917e..c5f8928c283c2 100644 --- a/tests/codegen-units/item-collection/drop-glue-eager.rs +++ b/tests/codegen-units/item-collection/drop-glue-eager.rs @@ -10,7 +10,6 @@ struct StructWithDrop { impl Drop for StructWithDrop { //~ MONO_ITEM fn ::drop - //~ MONO_ITEM fn ::pin_drop fn drop(&mut self) {} } @@ -25,7 +24,6 @@ enum EnumWithDrop { impl Drop for EnumWithDrop { //~ MONO_ITEM fn ::drop - //~ MONO_ITEM fn ::pin_drop fn drop(&mut self) {} } @@ -36,7 +34,6 @@ enum EnumNoDrop { // We should be able to monomorphize drops for struct with lifetimes. impl<'a> Drop for StructWithDropAndLt<'a> { //~ MONO_ITEM fn as std::ops::Drop>::drop - //~ MONO_ITEM fn as std::ops::Drop>::pin_drop fn drop(&mut self) {} } @@ -55,6 +52,5 @@ struct StructWithLtAndPredicate<'a: 'a> { // We should be able to monomorphize drops for struct with lifetimes. impl<'a> Drop for StructWithLtAndPredicate<'a> { //~ MONO_ITEM fn as std::ops::Drop>::drop - //~ MONO_ITEM fn as std::ops::Drop>::pin_drop fn drop(&mut self) {} } diff --git a/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs b/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs index 018d2ec6d0b4e..d8a8c3e7f2ed4 100644 --- a/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs +++ b/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs @@ -9,7 +9,6 @@ struct StructWithDtor(u32); impl Drop for StructWithDtor { //~ MONO_ITEM fn ::drop - //~ MONO_ITEM fn ::pin_drop fn drop(&mut self) {} } //~ MONO_ITEM fn start diff --git a/tests/codegen-units/item-collection/generic-drop-glue.rs b/tests/codegen-units/item-collection/generic-drop-glue.rs index 6dc07186800c5..beadf9ac0ae3d 100644 --- a/tests/codegen-units/item-collection/generic-drop-glue.rs +++ b/tests/codegen-units/item-collection/generic-drop-glue.rs @@ -39,7 +39,6 @@ struct NonGenericWithDrop(#[allow(dead_code)] i32); impl Drop for NonGenericWithDrop { //~ MONO_ITEM fn ::drop - //~ MONO_ITEM fn ::pin_drop fn drop(&mut self) {} } diff --git a/tests/codegen-units/item-collection/non-generic-closures.rs b/tests/codegen-units/item-collection/non-generic-closures.rs index 573427d8ddbfa..faa5c9c0163d8 100644 --- a/tests/codegen-units/item-collection/non-generic-closures.rs +++ b/tests/codegen-units/item-collection/non-generic-closures.rs @@ -74,6 +74,5 @@ struct PresentDrop; impl Drop for PresentDrop { //~ MONO_ITEM fn ::drop @@ non_generic_closures-cgu.0[External] - //~ MONO_ITEM fn ::pin_drop @@ non_generic_closures-cgu.0[External] fn drop(&mut self) {} } diff --git a/tests/codegen-units/item-collection/non-generic-drop-glue.rs b/tests/codegen-units/item-collection/non-generic-drop-glue.rs index ff9892a1049f1..750c1eb15c323 100644 --- a/tests/codegen-units/item-collection/non-generic-drop-glue.rs +++ b/tests/codegen-units/item-collection/non-generic-drop-glue.rs @@ -11,7 +11,6 @@ struct StructWithDrop { impl Drop for StructWithDrop { //~ MONO_ITEM fn ::drop - //~ MONO_ITEM fn ::pin_drop fn drop(&mut self) {} } @@ -26,7 +25,6 @@ enum EnumWithDrop { impl Drop for EnumWithDrop { //~ MONO_ITEM fn ::drop - //~ MONO_ITEM fn ::pin_drop fn drop(&mut self) {} } diff --git a/tests/codegen-units/item-collection/pin-drop.rs b/tests/codegen-units/item-collection/pin-drop.rs new file mode 100644 index 0000000000000..c191427889555 --- /dev/null +++ b/tests/codegen-units/item-collection/pin-drop.rs @@ -0,0 +1,41 @@ +#![feature(pin_ergonomics)] +// Ensure that we emit either `Drop::drop` or `Drop::pin_drop` for types that implement `Drop`. + +//@ compile-flags:-Clink-dead-code +//@ compile-flags:--crate-type=lib +//@ rustc-env:MONO_TEST=1 + +//~ MONO_ITEM fn std::ptr::drop_glue:: - shim(Some(StructWithDrop)) +struct StructWithDrop { + x: i32, +} + +impl Drop for StructWithDrop { + //~ MONO_ITEM fn ::drop + fn drop(&mut self) {} +} + +struct StructNoDrop { + x: i32, +} + +//~ MONO_ITEM fn std::ptr::drop_glue:: - shim(Some(StructWithPinDrop)) +struct StructWithPinDrop { + x: i32, +} + +impl Drop for StructWithPinDrop { + //~ MONO_ITEM fn ::pin_drop + fn pin_drop(&pin mut self) {} +} + +//~ MONO_ITEM fn std::ptr::drop_glue:: - shim(Some(StructPinV2WithPinDrop)) +#[pin_v2] +struct StructPinV2WithPinDrop { + x: i32, +} + +impl Drop for StructPinV2WithPinDrop { + //~ MONO_ITEM fn ::pin_drop + fn pin_drop(&pin mut self) {} +} diff --git a/tests/codegen-units/item-collection/transitive-drop-glue.rs b/tests/codegen-units/item-collection/transitive-drop-glue.rs index 5fbd3284513c9..4a38059067f32 100644 --- a/tests/codegen-units/item-collection/transitive-drop-glue.rs +++ b/tests/codegen-units/item-collection/transitive-drop-glue.rs @@ -13,7 +13,6 @@ struct Leaf; impl Drop for Leaf { //~ MONO_ITEM fn ::drop - //~ MONO_ITEM fn ::pin_drop fn drop(&mut self) {} } diff --git a/tests/codegen-units/item-collection/tuple-drop-glue.rs b/tests/codegen-units/item-collection/tuple-drop-glue.rs index 42c65abe939e0..60b42eadf0cf6 100644 --- a/tests/codegen-units/item-collection/tuple-drop-glue.rs +++ b/tests/codegen-units/item-collection/tuple-drop-glue.rs @@ -9,7 +9,6 @@ struct Dropped; impl Drop for Dropped { //~ MONO_ITEM fn ::drop - //~ MONO_ITEM fn ::pin_drop fn drop(&mut self) {} }