Skip to content

Commit e37ab57

Browse files
committed
FIX: Use raw pointer casts for MaybeUninit
The nodrop/fallback code is as it was, it uses the Array trait accessors as_ptr/as_ptr_mut; but we really want to do this properly with a raw pointer cast according to discussion with arielb. The idea is that we don't take a reference to a partially uninitialized array value -- we just extract a raw pointer to the first array element instead.
1 parent 25d1c1c commit e37ab57

File tree

3 files changed

+48
-16
lines changed

3 files changed

+48
-16
lines changed

src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ impl<A: Array> ArrayVec<A> {
581581
Err(self)
582582
} else {
583583
unsafe {
584-
let array = ptr::read(self.xs.ptr());
584+
let array = ptr::read(self.xs.ptr() as *const A);
585585
mem::forget(self);
586586
Ok(array)
587587
}
@@ -610,7 +610,7 @@ impl<A: Array> Deref for ArrayVec<A> {
610610
#[inline]
611611
fn deref(&self) -> &[A::Item] {
612612
unsafe {
613-
slice::from_raw_parts((*self.xs.ptr()).as_ptr(), self.len())
613+
slice::from_raw_parts(self.xs.ptr(), self.len())
614614
}
615615
}
616616
}
@@ -620,7 +620,7 @@ impl<A: Array> DerefMut for ArrayVec<A> {
620620
fn deref_mut(&mut self) -> &mut [A::Item] {
621621
let len = self.len();
622622
unsafe {
623-
slice::from_raw_parts_mut((*self.xs.ptr_mut()).as_mut_ptr(), len)
623+
slice::from_raw_parts_mut(self.xs.ptr_mut(), len)
624624
}
625625
}
626626
}

src/maybe_uninit.rs

+34-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11

22

3+
use array::Array;
34
use std::mem::ManuallyDrop;
45
use std::mem::uninitialized;
56

67
/// A combination of ManuallyDrop and “maybe uninitialized”;
78
/// this wraps a value that can be wholly or partially uninitialized;
89
/// it also has no drop regardless of the type of T.
10+
#[repr(C)]
911
pub struct MaybeUninit<T>(ManuallyDrop<T>);
1012

1113
impl<T> MaybeUninit<T> {
@@ -19,16 +21,42 @@ impl<T> MaybeUninit<T> {
1921
MaybeUninit(ManuallyDrop::new(v))
2022
}
2123

22-
/// Return a raw pointer to the interior
23-
pub fn ptr(&self) -> *const T {
24-
(&self.0) as *const ManuallyDrop<_> as *const T
24+
// Raw pointer casts written so that we don't reference or access the
25+
// uninitialized interior value
26+
27+
/// Return a raw pointer to the start of the interior array
28+
pub fn ptr(&self) -> *const T::Item
29+
where T: Array
30+
{
31+
self as *const _ as *const T::Item
2532
}
2633

27-
/// Return a raw pointer to the interior (mutable)
28-
pub fn ptr_mut(&mut self) -> *mut T {
29-
(&mut self.0) as *mut ManuallyDrop<_> as *mut T
34+
/// Return a mut raw pointer to the start of the interior array
35+
pub fn ptr_mut(&mut self) -> *mut T::Item
36+
where T: Array
37+
{
38+
self as *mut _ as *mut T::Item
3039
}
3140
}
3241

3342

3443

44+
#[test]
45+
fn test_offset() {
46+
use std::ptr;
47+
48+
let mut mu = MaybeUninit::from([1, 2, 3]);
49+
assert!(ptr::eq(mu.ptr(), &mu.0[0]));
50+
assert!(ptr::eq(mu.ptr_mut(), &mut mu.0[0]));
51+
}
52+
53+
#[test]
54+
#[cfg(feature = "std")]
55+
fn test_offset_string() {
56+
use std::ptr;
57+
58+
let s = String::from;
59+
let mut mu = MaybeUninit::from([s("a"), s("b")]);
60+
assert!(ptr::eq(mu.ptr(), &mu.0[0]));
61+
assert!(ptr::eq(mu.ptr_mut(), &mut mu.0[0]));
62+
}

src/maybe_uninit_nodrop.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
2+
use array::Array;
33
use nodrop::NoDrop;
44
use std::mem::uninitialized;
55

@@ -18,14 +18,18 @@ impl<T> MaybeUninit<T> {
1818
MaybeUninit(NoDrop::new(v))
1919
}
2020

21-
/// Return a raw pointer to the interior
22-
pub fn ptr(&self) -> *const T {
23-
&**(&self.0)
21+
/// Return a raw pointer to the start of the interior array
22+
pub fn ptr(&self) -> *const T::Item
23+
where T: Array
24+
{
25+
self.0.as_ptr()
2426
}
2527

26-
/// Return a raw pointer to the interior (mutable)
27-
pub fn ptr_mut(&mut self) -> *mut T {
28-
&mut **(&mut self.0)
28+
/// Return a mut raw pointer to the start of the interior array
29+
pub fn ptr_mut(&mut self) -> *mut T::Item
30+
where T: Array
31+
{
32+
self.0.as_mut_ptr()
2933
}
3034
}
3135

0 commit comments

Comments
 (0)