@@ -226,24 +226,45 @@ impl<H> WithHeader<H> {
226
226
// - Assumes that either `value` can be dereferenced, or is the
227
227
// `NonNull::dangling()` we use when both `T` and `H` are ZSTs.
228
228
unsafe fn drop < T : ?Sized > ( & self , value : * mut T ) {
229
+ struct DropGuard < H > {
230
+ ptr : NonNull < u8 > ,
231
+ value_layout : Layout ,
232
+ _marker : PhantomData < H > ,
233
+ }
234
+
235
+ impl < H > Drop for DropGuard < H > {
236
+ fn drop ( & mut self ) {
237
+ unsafe {
238
+ // SAFETY: Layout must have been computable if we're in drop
239
+ let ( layout, value_offset) =
240
+ WithHeader :: < H > :: alloc_layout ( self . value_layout ) . unwrap_unchecked ( ) ;
241
+
242
+ // Note: Don't deallocate if the layout size is zero, because the pointer
243
+ // didn't come from the allocator.
244
+ if layout. size ( ) != 0 {
245
+ alloc:: dealloc ( self . ptr . as_ptr ( ) . sub ( value_offset) , layout) ;
246
+ } else {
247
+ debug_assert ! (
248
+ value_offset == 0
249
+ && mem:: size_of:: <H >( ) == 0
250
+ && self . value_layout. size( ) == 0
251
+ ) ;
252
+ }
253
+ }
254
+ }
255
+ }
256
+
229
257
unsafe {
230
- let value_layout = Layout :: for_value_raw ( value) ;
231
- // SAFETY: Layout must have been computable if we're in drop
232
- let ( layout, value_offset) = Self :: alloc_layout ( value_layout) . unwrap_unchecked ( ) ;
258
+ // `_guard` will deallocate the memory when dropped, even if `drop_in_place` unwinds.
259
+ let _guard = DropGuard {
260
+ ptr : self . 0 ,
261
+ value_layout : Layout :: for_value_raw ( value) ,
262
+ _marker : PhantomData :: < H > ,
263
+ } ;
233
264
234
265
// We only drop the value because the Pointee trait requires that the metadata is copy
235
266
// aka trivially droppable.
236
267
ptr:: drop_in_place :: < T > ( value) ;
237
-
238
- // Note: Don't deallocate if the layout size is zero, because the pointer
239
- // didn't come from the allocator.
240
- if layout. size ( ) != 0 {
241
- alloc:: dealloc ( self . 0 . as_ptr ( ) . sub ( value_offset) , layout) ;
242
- } else {
243
- debug_assert ! (
244
- value_offset == 0 && mem:: size_of:: <H >( ) == 0 && value_layout. size( ) == 0
245
- ) ;
246
- }
247
268
}
248
269
}
249
270
0 commit comments