@@ -88,6 +88,7 @@ impl BlobVec {
88
88
/// # Safety
89
89
/// - index must be in bounds
90
90
/// - memory must be reserved and uninitialized
91
+ /// - the contents of `*value` must not be dropped by the caller
91
92
#[ inline]
92
93
pub unsafe fn initialize_unchecked ( & mut self , index : usize , value : * mut u8 ) {
93
94
debug_assert ! ( index < self . len( ) ) ;
@@ -97,12 +98,19 @@ impl BlobVec {
97
98
98
99
/// # Safety
99
100
/// - index must be in-bounds
100
- // - memory must be previously initialized
101
+ /// - memory must be previously initialized
102
+ /// - the contents of `*value` must not be dropped by the caller. (In fact,
103
+ /// this function may overwrite them.)
101
104
pub unsafe fn replace_unchecked ( & mut self , index : usize , value : * mut u8 ) {
102
105
debug_assert ! ( index < self . len( ) ) ;
103
106
let ptr = self . get_unchecked ( index) ;
104
- ( self . drop ) ( ptr) ;
105
- std:: ptr:: copy_nonoverlapping ( value, ptr, self . item_layout . size ( ) ) ;
107
+ // We need to make sure that we don't still contain the old value before
108
+ // calling `drop`. Otherwise, if `drop` panics, then when the collection
109
+ // is dropped stack unwinding, its `Drop` impl will call `drop` again
110
+ // for the old value, so we get a double drop. Also, the new value
111
+ // wouldn't be dropped.
112
+ std:: ptr:: swap_nonoverlapping ( value, ptr, self . item_layout . size ( ) ) ;
113
+ ( self . drop ) ( value) ;
106
114
}
107
115
108
116
/// increases the length by one (and grows the vec if needed) with uninitialized memory and
0 commit comments