@@ -98,7 +98,7 @@ use core::hint::unreachable_unchecked;
98
98
use core:: iter:: { repeat, FromIterator , FusedIterator , IntoIterator } ;
99
99
use core:: mem;
100
100
use core:: mem:: MaybeUninit ;
101
- use core:: ops:: { self , RangeBounds } ;
101
+ use core:: ops:: { self , Range , RangeBounds } ;
102
102
use core:: ptr:: { self , NonNull } ;
103
103
use core:: slice:: { self , SliceIndex } ;
104
104
@@ -975,8 +975,6 @@ impl<A: Array> SmallVec<A> {
975
975
976
976
/// Insert multiple elements at position `index`, shifting all following elements toward the
977
977
/// back.
978
- ///
979
- /// Note: when the iterator panics, this can leak memory.
980
978
pub fn insert_many < I : IntoIterator < Item = A :: Item > > ( & mut self , index : usize , iterable : I ) {
981
979
let iter = iterable. into_iter ( ) ;
982
980
if index == self . len ( ) {
@@ -991,27 +989,41 @@ impl<A: Array> SmallVec<A> {
991
989
unsafe {
992
990
let old_len = self . len ( ) ;
993
991
assert ! ( index <= old_len) ;
994
- let mut ptr = self . as_mut_ptr ( ) . add ( index) ;
992
+ let start = self . as_mut_ptr ( ) ;
993
+ let mut ptr = start. add ( index) ;
995
994
996
995
// Move the trailing elements.
997
996
ptr:: copy ( ptr, ptr. add ( lower_size_bound) , old_len - index) ;
998
997
999
998
// In case the iterator panics, don't double-drop the items we just copied above.
1000
- self . set_len ( index) ;
999
+ self . set_len ( 0 ) ;
1000
+ let mut guard = DropOnPanic {
1001
+ start,
1002
+ skip : index..( index + lower_size_bound) ,
1003
+ len : old_len + lower_size_bound,
1004
+ } ;
1001
1005
1002
1006
let mut num_added = 0 ;
1003
1007
for element in iter {
1004
1008
let mut cur = ptr. add ( num_added) ;
1005
1009
if num_added >= lower_size_bound {
1006
1010
// Iterator provided more elements than the hint. Move trailing items again.
1007
1011
self . reserve ( 1 ) ;
1008
- ptr = self . as_mut_ptr ( ) . add ( index) ;
1012
+ let start = self . as_mut_ptr ( ) ;
1013
+ ptr = start. add ( index) ;
1009
1014
cur = ptr. add ( num_added) ;
1010
1015
ptr:: copy ( cur, cur. add ( 1 ) , old_len - index) ;
1016
+
1017
+ guard. start = start;
1018
+ guard. len += 1 ;
1019
+ guard. skip . end += 1 ;
1011
1020
}
1012
1021
ptr:: write ( cur, element) ;
1022
+ guard. skip . start += 1 ;
1013
1023
num_added += 1 ;
1014
1024
}
1025
+ mem:: forget ( guard) ;
1026
+
1015
1027
if num_added < lower_size_bound {
1016
1028
// Iterator provided fewer elements than the hint
1017
1029
ptr:: copy (
@@ -1023,6 +1035,24 @@ impl<A: Array> SmallVec<A> {
1023
1035
1024
1036
self . set_len ( old_len + num_added) ;
1025
1037
}
1038
+
1039
+ struct DropOnPanic < T > {
1040
+ start : * mut T ,
1041
+ skip : Range < usize > ,
1042
+ len : usize ,
1043
+ }
1044
+
1045
+ impl < T > Drop for DropOnPanic < T > {
1046
+ fn drop ( & mut self ) {
1047
+ for i in 0 ..self . len {
1048
+ if !self . skip . contains ( & i) {
1049
+ unsafe {
1050
+ ptr:: drop_in_place ( self . start . add ( i) ) ;
1051
+ }
1052
+ }
1053
+ }
1054
+ }
1055
+ }
1026
1056
}
1027
1057
1028
1058
/// Convert a SmallVec to a Vec, without reallocating if the SmallVec has already spilled onto
@@ -1249,6 +1279,22 @@ impl<A: Array> SmallVec<A> {
1249
1279
data : SmallVecData :: from_heap ( ptr, length) ,
1250
1280
}
1251
1281
}
1282
+
1283
+ /// Returns a raw pointer to the vector's buffer.
1284
+ pub fn as_ptr ( & self ) -> * const A :: Item {
1285
+ // We shadow the slice method of the same name to avoid going through
1286
+ // `deref`, which creates an intermediate reference that may place
1287
+ // additional safety constraints on the contents of the slice.
1288
+ self . triple ( ) . 0
1289
+ }
1290
+
1291
+ /// Returns a raw mutable pointer to the vector's buffer.
1292
+ pub fn as_mut_ptr ( & mut self ) -> * mut A :: Item {
1293
+ // We shadow the slice method of the same name to avoid going through
1294
+ // `deref_mut`, which creates an intermediate reference that may place
1295
+ // additional safety constraints on the contents of the slice.
1296
+ self . triple_mut ( ) . 0
1297
+ }
1252
1298
}
1253
1299
1254
1300
impl < A : Array > SmallVec < A >
0 commit comments