From 8acccdc355b25a9c99c38a7685ad4013562d2ec8 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 14 Dec 2024 21:20:15 -0800 Subject: [PATCH] Use `PtrMetadata` instead of `Len` in slice drop shims --- .../rustc_mir_dataflow/src/elaborate_drops.rs | 75 ++++++++++++++++--- ...ring;42].AddMovesForPackedDrops.before.mir | 42 ++++++----- ...[String].AddMovesForPackedDrops.before.mir | 2 +- 3 files changed, 92 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 494b7d54d8a..f8a84674947 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -1,4 +1,4 @@ -use std::{fmt, iter}; +use std::{fmt, iter, mem}; use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; use rustc_hir::lang_items::LangItem; @@ -6,6 +6,7 @@ use rustc_index::Idx; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::span_bug; +use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt}; use rustc_span::DUMMY_SP; @@ -738,8 +739,13 @@ where loop_block } - fn open_drop_for_array(&mut self, ety: Ty<'tcx>, opt_size: Option) -> BasicBlock { - debug!("open_drop_for_array({:?}, {:?})", ety, opt_size); + fn open_drop_for_array( + &mut self, + array_ty: Ty<'tcx>, + ety: Ty<'tcx>, + opt_size: Option, + ) -> BasicBlock { + debug!("open_drop_for_array({:?}, {:?}, {:?})", array_ty, ety, opt_size); let tcx = self.tcx(); if let Some(size) = opt_size { @@ -801,13 +807,50 @@ where } } - self.drop_loop_pair(ety) + let array_ptr_ty = Ty::new_mut_ptr(tcx, array_ty); + let array_ptr = self.new_temp(array_ptr_ty); + + let slice_ty = Ty::new_slice(tcx, ety); + let slice_ptr_ty = Ty::new_mut_ptr(tcx, slice_ty); + let slice_ptr = self.new_temp(slice_ptr_ty); + + let mut delegate_block = BasicBlockData { + statements: vec![ + self.assign(Place::from(array_ptr), Rvalue::RawPtr(Mutability::Mut, self.place)), + self.assign( + Place::from(slice_ptr), + Rvalue::Cast( + CastKind::PointerCoercion( + PointerCoercion::Unsize, + CoercionSource::Implicit, + ), + Operand::Move(Place::from(array_ptr)), + slice_ptr_ty, + ), + ), + ], + is_cleanup: self.unwind.is_cleanup(), + terminator: None, + }; + + let array_place = mem::replace( + &mut self.place, + Place::from(slice_ptr).project_deeper(&[PlaceElem::Deref], tcx), + ); + let slice_block = self.drop_loop_pair_for_slice(ety); + self.place = array_place; + + delegate_block.terminator = Some(Terminator { + source_info: self.source_info, + kind: TerminatorKind::Goto { target: slice_block }, + }); + self.elaborator.patch().new_block(delegate_block) } /// Creates a pair of drop-loops of `place`, which drops its contents, even /// in the case of 1 panic. - fn drop_loop_pair(&mut self, ety: Ty<'tcx>) -> BasicBlock { - debug!("drop_loop_pair({:?})", ety); + fn drop_loop_pair_for_slice(&mut self, ety: Ty<'tcx>) -> BasicBlock { + debug!("drop_loop_pair_for_slice({:?})", ety); let tcx = self.tcx(); let len = self.new_temp(tcx.types.usize); let cur = self.new_temp(tcx.types.usize); @@ -817,10 +860,24 @@ where let loop_block = self.drop_loop(self.succ, cur, len, ety, unwind); + let [PlaceElem::Deref] = self.place.projection.as_slice() else { + span_bug!( + self.source_info.span, + "Expected place for slice drop shim to be *_n, but it's {:?}", + self.place, + ); + }; + let zero = self.constant_usize(0); let block = BasicBlockData { statements: vec![ - self.assign(len.into(), Rvalue::Len(self.place)), + self.assign( + len.into(), + Rvalue::UnaryOp( + UnOp::PtrMetadata, + Operand::Copy(Place::from(self.place.local)), + ), + ), self.assign(cur.into(), Rvalue::Use(zero)), ], is_cleanup: unwind.is_cleanup(), @@ -863,9 +920,9 @@ where ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind), ty::Array(ety, size) => { let size = size.try_to_target_usize(self.tcx()); - self.open_drop_for_array(*ety, size) + self.open_drop_for_array(ty, *ety, size) } - ty::Slice(ety) => self.drop_loop_pair(*ety), + ty::Slice(ety) => self.drop_loop_pair_for_slice(*ety), _ => span_bug!(self.source_info.span, "open drop from non-ADT `{:?}`", ty), } diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir index 197a93e99d3..13df2195ab0 100644 --- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir @@ -2,15 +2,17 @@ fn std::ptr::drop_in_place(_1: *mut [String; 42]) -> () { let mut _0: (); - let mut _2: usize; - let mut _3: usize; - let mut _4: *mut std::string::String; - let mut _5: bool; + let mut _2: *mut [std::string::String; 42]; + let mut _3: *mut [std::string::String]; + let mut _4: usize; + let mut _5: usize; let mut _6: *mut std::string::String; let mut _7: bool; + let mut _8: *mut std::string::String; + let mut _9: bool; bb0: { - goto -> bb8; + goto -> bb9; } bb1: { @@ -22,34 +24,40 @@ fn std::ptr::drop_in_place(_1: *mut [String; 42]) -> () { } bb3 (cleanup): { - _4 = &raw mut (*_1)[_3]; - _3 = Add(move _3, const 1_usize); - drop((*_4)) -> [return: bb4, unwind terminate(cleanup)]; + _6 = &raw mut (*_3)[_5]; + _5 = Add(move _5, const 1_usize); + drop((*_6)) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { - _5 = Eq(copy _3, copy _2); - switchInt(move _5) -> [0: bb3, otherwise: bb2]; + _7 = Eq(copy _5, copy _4); + switchInt(move _7) -> [0: bb3, otherwise: bb2]; } bb5: { - _6 = &raw mut (*_1)[_3]; - _3 = Add(move _3, const 1_usize); - drop((*_6)) -> [return: bb6, unwind: bb4]; + _8 = &raw mut (*_3)[_5]; + _5 = Add(move _5, const 1_usize); + drop((*_8)) -> [return: bb6, unwind: bb4]; } bb6: { - _7 = Eq(copy _3, copy _2); - switchInt(move _7) -> [0: bb5, otherwise: bb1]; + _9 = Eq(copy _5, copy _4); + switchInt(move _9) -> [0: bb5, otherwise: bb1]; } bb7: { - _2 = Len((*_1)); - _3 = const 0_usize; + _4 = PtrMetadata(copy _3); + _5 = const 0_usize; goto -> bb6; } bb8: { goto -> bb7; } + + bb9: { + _2 = &raw mut (*_1); + _3 = move _2 as *mut [std::string::String] (PointerCoercion(Unsize, Implicit)); + goto -> bb8; + } } diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir index 4d1eaa6ffe3..0633b765644 100644 --- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir @@ -44,7 +44,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () { } bb7: { - _2 = Len((*_1)); + _2 = PtrMetadata(copy _1); _3 = const 0_usize; goto -> bb6; }