@@ -226,24 +226,45 @@ impl<H> WithHeader<H> {
226226 // - Assumes that either `value` can be dereferenced, or is the
227227 // `NonNull::dangling()` we use when both `T` and `H` are ZSTs.
228228 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+
229257 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+ } ;
233264
234265 // We only drop the value because the Pointee trait requires that the metadata is copy
235266 // aka trivially droppable.
236267 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- }
247268 }
248269 }
249270
0 commit comments