Skip to content

Commit b3e30ea

Browse files
japaricXOSplicer
authored andcommitted
internally use MaybeUninit
which has been proposed in rust-lang/rfcs#1892
1 parent d695f3c commit b3e30ea

File tree

4 files changed

+66
-69
lines changed

4 files changed

+66
-69
lines changed

src/__core.rs

+37-32
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,51 @@
22
33
pub mod mem {
44
#[cfg(not(feature = "const-fn"))]
5-
pub use core::mem::uninitialized;
5+
pub use core::mem;
66
pub use core::mem::{replace, zeroed, ManuallyDrop};
77

8+
// See RFC 1892
89
#[cfg(feature = "const-fn")]
9-
pub const unsafe fn uninitialized<T>() -> T {
10-
#[allow(unions_with_drop_fields)]
11-
union U<T> {
12-
none: (),
13-
some: T,
14-
}
10+
pub union MaybeUninit<T> {
11+
uninit: (),
12+
value: ManuallyDrop<T>,
13+
}
1514

16-
U { none: () }.some
15+
// workaround to get this to compile on stable ("unions with non-`Copy` fields are unstable")
16+
#[cfg(not(feature = "const-fn"))]
17+
pub struct MaybeUninit<T> {
18+
value: ManuallyDrop<T>
1719
}
18-
}
1920

20-
#[cfg(feature = "const-fn")] // Remove this if there are more tests
21-
#[cfg(test)]
22-
mod test {
23-
use __core;
24-
use __core::mem::ManuallyDrop;
25-
use core;
21+
impl<T> MaybeUninit<T> {
22+
#[cfg(feature = "const-fn")]
23+
pub const unsafe fn uninitialized() -> Self {
24+
MaybeUninit { uninit: () }
25+
}
2626

27-
#[cfg(feature = "const-fn")]
28-
#[test]
29-
fn static_uninitzialized() {
30-
static mut I: i32 = unsafe { __core::mem::uninitialized() };
31-
// Initialize before drop
32-
unsafe { core::ptr::write(&mut I as *mut i32, 42) };
33-
unsafe { assert_eq!(I, 42) };
34-
}
27+
#[cfg(not(feature = "const-fn"))]
28+
pub unsafe fn uninitialized() -> Self {
29+
mem::uninitialized()
30+
}
3531

36-
#[cfg(feature = "const-fn")]
37-
#[test]
38-
fn static_new_manually_drop() {
39-
static mut M: ManuallyDrop<i32> = ManuallyDrop::new(42);
40-
unsafe {
41-
assert_eq!(*M, 42);
32+
/// Get a reference to the contained value.
33+
///
34+
/// # Unsafety
35+
///
36+
/// It is up to the caller to guarantee that the the `MaybeUninit` really is in an
37+
/// initialized state, otherwise this will immediately cause undefined behavior.
38+
pub unsafe fn get_ref(&self) -> &T {
39+
&*self.value
4240
}
43-
// Drop before deinitialization
44-
unsafe { core::ptr::drop_in_place(&mut M as &mut i32 as *mut i32) };
45-
}
4641

42+
/// Get a mutable reference to the contained value.
43+
///
44+
/// # Unsafety
45+
///
46+
/// It is up to the caller to guarantee that the the `MaybeUninit` really is in an
47+
/// initialized state, otherwise this will immediately cause undefined behavior.
48+
pub unsafe fn get_mut(&mut self) -> &mut T {
49+
&mut *self.value
50+
}
51+
}
4752
}

src/ring_buffer/mod.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ use core::ptr;
88
#[cfg(not(feature = "smaller-atomics"))]
99
use core::sync::atomic::{AtomicUsize, Ordering};
1010

11-
use generic_array::typenum::{Sum, U1, Unsigned};
11+
use generic_array::typenum::{Sum, Unsigned, U1};
1212
use generic_array::{ArrayLength, GenericArray};
1313

1414
pub use self::spsc::{Consumer, Producer};
15-
use __core::mem::{self, ManuallyDrop};
15+
use __core::mem::MaybeUninit;
1616

1717
mod spsc;
1818

@@ -230,7 +230,7 @@ where
230230
// this is where we enqueue new items
231231
tail: Atomic<U>,
232232

233-
buffer: ManuallyDrop<GenericArray<T, Sum<N, U1>>>,
233+
buffer: MaybeUninit<GenericArray<T, Sum<N, U1>>>,
234234
}
235235

236236
impl<T, N, U> RingBuffer<T, N, U>
@@ -334,7 +334,7 @@ macro_rules! impl_ {
334334
/// Creates an empty ring buffer with a fixed capacity of `N`
335335
pub const fn $uxx() -> Self {
336336
RingBuffer {
337-
buffer: ManuallyDrop::new(unsafe { mem::uninitialized() }),
337+
buffer: unsafe { MaybeUninit::uninitialized() },
338338
head: Atomic::new(0),
339339
tail: Atomic::new(0),
340340
}
@@ -348,7 +348,7 @@ macro_rules! impl_ {
348348
let head = self.head.get_mut();
349349
let tail = self.tail.get_mut();
350350

351-
let buffer = self.buffer.as_slice();
351+
let buffer = unsafe { self.buffer.get_ref() };
352352

353353
if *head != *tail {
354354
let item = unsafe { ptr::read(buffer.get_unchecked(usize::from(*head))) };
@@ -387,7 +387,7 @@ macro_rules! impl_ {
387387

388388
let tail = self.tail.get_mut();
389389

390-
let buffer = self.buffer.as_mut_slice();
390+
let buffer = unsafe { self.buffer.get_mut() };
391391

392392
let next_tail = (*tail + 1) % n;
393393
// NOTE(ptr::write) the memory slot that we are about to write to is
@@ -473,7 +473,7 @@ macro_rules! iterator {
473473
let head = self.rb.head.load_relaxed().into();
474474

475475
let capacity = self.rb.capacity().into() + 1;
476-
let buffer = self.rb.buffer.$asref();
476+
let buffer = unsafe { self.rb.buffer.$asref() };
477477
let ptr: $ptr = buffer.$asptr();
478478
let i = (head + self.index) % capacity;
479479
self.index += 1;
@@ -498,8 +498,8 @@ macro_rules! make_ref_mut {
498498
};
499499
}
500500

501-
iterator!(struct Iter -> &'a T, *const T, as_slice, as_ptr, make_ref);
502-
iterator!(struct IterMut -> &'a mut T, *mut T, as_mut_slice, as_mut_ptr, make_ref_mut);
501+
iterator!(struct Iter -> &'a T, *const T, get_ref, as_ptr, make_ref);
502+
iterator!(struct IterMut -> &'a mut T, *mut T, get_mut, as_mut_ptr, make_ref_mut);
503503

504504
#[cfg(test)]
505505
mod tests {

src/ring_buffer/spsc.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use core::marker::PhantomData;
22
use core::ops::Add;
33
use core::ptr::{self, NonNull};
44

5-
use generic_array::typenum::{Sum, U1, Unsigned};
5+
use generic_array::typenum::{Sum, Unsigned, U1};
66
use generic_array::ArrayLength;
77

88
use ring_buffer::{RingBuffer, Uxx};
@@ -47,8 +47,7 @@ where
4747
Sum<N, U1>: ArrayLength<T>,
4848
T: Send,
4949
U: Uxx,
50-
{
51-
}
50+
{}
5251

5352
/// A ring buffer "producer"; it can enqueue items into the ring buffer
5453
// NOTE the producer semantically owns the `tail` pointer of the ring buffer
@@ -69,8 +68,7 @@ where
6968
Sum<N, U1>: ArrayLength<T>,
7069
T: Send,
7170
U: Uxx,
72-
{
73-
}
71+
{}
7472

7573
macro_rules! impl_ {
7674
($uxx:ident) => {
@@ -114,7 +112,7 @@ macro_rules! impl_ {
114112
let rb = self.rb.as_ref();
115113

116114
let n = rb.capacity() + 1;
117-
let buffer: &[T] = rb.buffer.as_ref();
115+
let buffer = rb.buffer.get_ref();
118116

119117
let item = ptr::read(buffer.get_unchecked(usize::from(head)));
120118
rb.head.store_release((head + 1) % n);
@@ -183,7 +181,7 @@ macro_rules! impl_ {
183181
let rb = self.rb.as_mut();
184182

185183
let n = rb.capacity() + 1;
186-
let buffer: &mut [T] = rb.buffer.as_mut();
184+
let buffer = rb.buffer.get_mut();
187185

188186
let next_tail = (tail + 1) % n;
189187
// NOTE(ptr::write) the memory slot that we are about to write to is

src/vec.rs

+15-21
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use core::{fmt, ops, ptr, slice};
22

33
use generic_array::{ArrayLength, GenericArray};
44

5-
use __core::mem::{self, ManuallyDrop};
5+
use __core::mem::MaybeUninit;
66

77
use core::iter::FromIterator;
88

@@ -39,7 +39,7 @@ pub struct Vec<T, N>
3939
where
4040
N: ArrayLength<T>,
4141
{
42-
buffer: ManuallyDrop<GenericArray<T, N>>,
42+
buffer: MaybeUninit<GenericArray<T, N>>,
4343
len: usize,
4444
}
4545

@@ -52,7 +52,7 @@ where
5252
/// Constructs a new, empty vector with a fixed capacity of `N`
5353
pub const fn new() -> Self {
5454
Vec {
55-
buffer: ManuallyDrop::new(unsafe { mem::uninitialized() }),
55+
buffer: unsafe { MaybeUninit::uninitialized() },
5656
len: 0,
5757
}
5858
}
@@ -112,7 +112,7 @@ where
112112
pub(crate) unsafe fn pop_unchecked(&mut self) -> T {
113113
debug_assert!(!self.is_empty());
114114

115-
let buffer = self.buffer.as_slice();
115+
let buffer = self.buffer.get_ref();
116116

117117
self.len -= 1;
118118
let item = ptr::read(buffer.get_unchecked(self.len));
@@ -132,7 +132,7 @@ where
132132
}
133133

134134
pub(crate) unsafe fn push_unchecked(&mut self, item: T) {
135-
let buffer = self.buffer.as_mut_slice();
135+
let buffer = self.buffer.get_mut();
136136

137137
// NOTE(ptr::write) the memory slot that we are about to write to is uninitialized. We
138138
// use `ptr::write` to avoid running `T`'s destructor on the uninitialized memory
@@ -314,7 +314,6 @@ where
314314
}
315315
}
316316

317-
318317
impl<T, N> FromIterator<T> for Vec<T, N>
319318
where
320319
N: ArrayLength<T>,
@@ -345,15 +344,15 @@ where
345344
next: usize,
346345
}
347346

348-
impl <T, N> Iterator for IntoIter<T, N>
347+
impl<T, N> Iterator for IntoIter<T, N>
349348
where
350349
N: ArrayLength<T>,
351350
{
352351
type Item = T;
353352
fn next(&mut self) -> Option<Self::Item> {
354353
if self.next < self.vec.len() {
355-
let buffer = self.vec.buffer.as_slice();
356-
let item = unsafe {ptr::read(buffer.get_unchecked(self.next))};
354+
let buffer = unsafe { self.vec.buffer.get_ref() };
355+
let item = unsafe { ptr::read(buffer.get_unchecked(self.next)) };
357356
self.next += 1;
358357
Some(item)
359358
} else {
@@ -362,7 +361,7 @@ where
362361
}
363362
}
364363

365-
impl <T, N> Drop for IntoIter<T, N>
364+
impl<T, N> Drop for IntoIter<T, N>
366365
where
367366
N: ArrayLength<T>,
368367
{
@@ -376,18 +375,15 @@ where
376375
}
377376
}
378377

379-
impl <T, N> IntoIterator for Vec<T, N>
378+
impl<T, N> IntoIterator for Vec<T, N>
380379
where
381380
N: ArrayLength<T>,
382381
{
383382
type Item = T;
384383
type IntoIter = IntoIter<T, N>;
385384

386385
fn into_iter(self) -> Self::IntoIter {
387-
IntoIter {
388-
vec: self,
389-
next: 0,
390-
}
386+
IntoIter { vec: self, next: 0 }
391387
}
392388
}
393389

@@ -448,7 +444,7 @@ where
448444
type Target = [T];
449445

450446
fn deref(&self) -> &[T] {
451-
let buffer = self.buffer.as_slice();
447+
let buffer = unsafe { self.buffer.get_ref() };
452448
// NOTE(unsafe) avoid bound checks in the slicing operation
453449
// &buffer[..self.len]
454450
unsafe { slice::from_raw_parts(buffer.as_ptr(), self.len) }
@@ -461,7 +457,7 @@ where
461457
{
462458
fn deref_mut(&mut self) -> &mut [T] {
463459
let len = self.len();
464-
let buffer = self.buffer.as_mut_slice();
460+
let buffer = unsafe { self.buffer.get_mut() };
465461

466462
// NOTE(unsafe) avoid bound checks in the slicing operation
467463
// &mut buffer[..len]
@@ -521,7 +517,7 @@ mod tests {
521517
}
522518

523519
macro_rules! droppable {
524-
() => (
520+
() => {
525521
struct Droppable;
526522
impl Droppable {
527523
fn new() -> Self {
@@ -540,12 +536,11 @@ mod tests {
540536
}
541537

542538
static mut COUNT: i32 = 0;
543-
)
539+
};
544540
}
545541

546542
#[test]
547543
fn drop() {
548-
549544
droppable!();
550545

551546
{
@@ -660,7 +655,6 @@ mod tests {
660655

661656
#[test]
662657
fn iter_move_drop() {
663-
664658
droppable!();
665659

666660
{

0 commit comments

Comments
 (0)