Skip to content

Commit 2a33979

Browse files
committed
FIX: Fix .extend() for ArrayVec with zero-sized type elements
The raw pointer walk did not do the right thing for ZST, because when offsets are zero, the start and end pointer would be the same and the loop ends before incrementing the length correctly.
1 parent f7381fa commit 2a33979

File tree

1 file changed

+22
-4
lines changed

1 file changed

+22
-4
lines changed

src/lib.rs

+22-4
Original file line numberDiff line numberDiff line change
@@ -926,8 +926,8 @@ impl<A: Array> Extend<A::Item> for ArrayVec<A> {
926926
let take = self.capacity() - self.len();
927927
unsafe {
928928
let len = self.len();
929-
let mut ptr = self.as_mut_ptr().offset(len as isize);
930-
let end_ptr = ptr.offset(take as isize);
929+
let mut ptr = raw_ptr_add(self.as_mut_ptr(), len);
930+
let end_ptr = raw_ptr_add(ptr, take);
931931
// Keep the length in a separate variable, write it back on scope
932932
// exit. To help the compiler with alias analysis and stuff.
933933
// We update the length to handle panic in the iteration of the
@@ -943,8 +943,8 @@ impl<A: Array> Extend<A::Item> for ArrayVec<A> {
943943
loop {
944944
if ptr == end_ptr { break; }
945945
if let Some(elt) = iter.next() {
946-
ptr::write(ptr, elt);
947-
ptr = ptr.offset(1);
946+
raw_ptr_write(ptr, elt);
947+
ptr = raw_ptr_add(ptr, 1);
948948
guard.data += 1;
949949
} else {
950950
break;
@@ -954,6 +954,24 @@ impl<A: Array> Extend<A::Item> for ArrayVec<A> {
954954
}
955955
}
956956

957+
/// Rawptr add but uses arithmetic distance for ZST
958+
unsafe fn raw_ptr_add<T>(ptr: *mut T, offset: usize) -> *mut T {
959+
if mem::size_of::<T>() == 0 {
960+
// Special case for ZST
961+
(ptr as usize).wrapping_add(offset) as _
962+
} else {
963+
ptr.offset(offset as isize)
964+
}
965+
}
966+
967+
unsafe fn raw_ptr_write<T>(ptr: *mut T, value: T) {
968+
if mem::size_of::<T>() == 0 {
969+
/* nothing */
970+
} else {
971+
ptr::write(ptr, value)
972+
}
973+
}
974+
957975
/// Create an `ArrayVec` from an iterator.
958976
///
959977
/// Does not extract more items than there is space for. No error

0 commit comments

Comments
 (0)