Skip to content

Commit 1f40252

Browse files
committed
Make from_elem panic-safe
Fixes #101
1 parent 26b2490 commit 1f40252

File tree

1 file changed

+32
-7
lines changed

1 file changed

+32
-7
lines changed

lib.rs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -946,19 +946,17 @@ impl<A: Array> SmallVec<A> where A::Item: Clone {
946946
if n > A::size() {
947947
vec![elem; n].into()
948948
} else {
949+
let mut v = SmallVec::<A>::new();
949950
unsafe {
950-
let mut arr: A = ::std::mem::uninitialized();
951-
let ptr = arr.ptr_mut();
951+
let (ptr, len_ptr, _) = v.triple_mut();
952+
let mut local_len = SetLenOnDrop::new(len_ptr);
952953

953954
for i in 0..n as isize {
954955
::std::ptr::write(ptr.offset(i), elem.clone());
955-
}
956-
957-
SmallVec {
958-
capacity: n,
959-
data: SmallVecData::from_inline(arr),
956+
local_len.increment_len(1);
960957
}
961958
}
959+
v
962960
}
963961
}
964962
}
@@ -1346,6 +1344,33 @@ pub unsafe trait Array {
13461344
fn ptr_mut(&mut self) -> *mut Self::Item;
13471345
}
13481346

1347+
/// Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
1348+
///
1349+
/// Copied from https://github.com/rust-lang/rust/pull/36355
1350+
struct SetLenOnDrop<'a> {
1351+
len: &'a mut usize,
1352+
local_len: usize,
1353+
}
1354+
1355+
impl<'a> SetLenOnDrop<'a> {
1356+
#[inline]
1357+
fn new(len: &'a mut usize) -> Self {
1358+
SetLenOnDrop { local_len: *len, len: len }
1359+
}
1360+
1361+
#[inline]
1362+
fn increment_len(&mut self, increment: usize) {
1363+
self.local_len += increment;
1364+
}
1365+
}
1366+
1367+
impl<'a> Drop for SetLenOnDrop<'a> {
1368+
#[inline]
1369+
fn drop(&mut self) {
1370+
*self.len = self.local_len;
1371+
}
1372+
}
1373+
13491374
macro_rules! impl_array(
13501375
($($size:expr),+) => {
13511376
$(

0 commit comments

Comments
 (0)