Skip to content

Commit 2419cb5

Browse files
committed
Add impl Index for MaybeUninit<[T; N]>
Add impl IndexMut for `MaybeUninit<[T; N]>` Add impl IntoIterator for `&mut MaybeUninit<[T; N]>` Add `MaybeUninit<[T; N]>::iter_mut` method
1 parent b69fe57 commit 2419cb5

File tree

3 files changed

+105
-0
lines changed

3 files changed

+105
-0
lines changed

library/core/src/mem/maybe_uninit.rs

+54
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use crate::any::type_name;
22
use crate::fmt;
33
use crate::intrinsics;
44
use crate::mem::ManuallyDrop;
5+
use crate::ops::{Index, IndexMut};
56
use crate::ptr;
7+
use crate::slice::IterMut;
68

79
/// A wrapper type to construct uninitialized instances of `T`.
810
///
@@ -1158,3 +1160,55 @@ impl<T> MaybeUninit<T> {
11581160
unsafe { MaybeUninit::slice_assume_init_mut(this) }
11591161
}
11601162
}
1163+
1164+
impl<T, const N: usize> Index<usize> for MaybeUninit<[T; N]> {
1165+
type Output = MaybeUninit<T>;
1166+
1167+
#[inline]
1168+
fn index(&self, index: usize) -> &Self::Output {
1169+
Index::index(self.as_ref(), index)
1170+
}
1171+
}
1172+
1173+
impl<T, const N: usize> IndexMut<usize> for MaybeUninit<[T; N]> {
1174+
#[inline]
1175+
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
1176+
IndexMut::index_mut(self.as_mut(), index)
1177+
}
1178+
}
1179+
1180+
impl<T, const N: usize> AsRef<[MaybeUninit<T>]> for MaybeUninit<[T; N]> {
1181+
#[inline]
1182+
fn as_ref(&self) -> &[MaybeUninit<T>] {
1183+
let data = self.as_ptr().cast::<MaybeUninit<T>>();
1184+
// SAFETY: MaybeUninit<[T; N]> and [MaybeUninit<T>; N] have the same layout
1185+
// data points to N consecutive properly initialized values of type MaybeUninit<T>.
1186+
unsafe { crate::slice::from_raw_parts(data, N) }
1187+
}
1188+
}
1189+
1190+
impl<T, const N: usize> AsMut<[MaybeUninit<T>]> for MaybeUninit<[T; N]> {
1191+
#[inline]
1192+
fn as_mut(&mut self) -> &mut [MaybeUninit<T>] {
1193+
let data = self.as_mut_ptr().cast::<MaybeUninit<T>>();
1194+
// SAFETY: MaybeUninit<[T; N]> and [MaybeUninit<T>; N] have the same layout
1195+
// data points to N consecutive properly initialized values of type MaybeUninit<T>.
1196+
unsafe { crate::slice::from_raw_parts_mut(data, N) }
1197+
}
1198+
}
1199+
1200+
impl<'a, T, const N: usize> IntoIterator for &'a mut MaybeUninit<[T; N]> {
1201+
type Item = &'a mut MaybeUninit<T>;
1202+
type IntoIter = IterMut<'a, MaybeUninit<T>>;
1203+
1204+
fn into_iter(self) -> IterMut<'a, MaybeUninit<T>> {
1205+
self.as_mut().iter_mut()
1206+
}
1207+
}
1208+
1209+
#[unstable(feature = "maybe_uninit_array_index", issue = "none")]
1210+
impl<T, const N: usize> MaybeUninit<[T; N]> {
1211+
pub fn iter_mut(&mut self) -> IterMut<'_, MaybeUninit<T>> {
1212+
self.as_mut().iter_mut()
1213+
}
1214+
}

library/core/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#![feature(slice_partition_at_index)]
3535
#![feature(maybe_uninit_uninit_array)]
3636
#![feature(maybe_uninit_array_assume_init)]
37+
#![feature(maybe_uninit_array_index)]
3738
#![feature(maybe_uninit_extra)]
3839
#![feature(maybe_uninit_write_slice)]
3940
#![feature(min_specialization)]

library/core/tests/mem.rs

+50
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,53 @@ fn uninit_const_assume_init_read() {
269269
const FOO: u32 = unsafe { MaybeUninit::new(42).assume_init_read() };
270270
assert_eq!(FOO, 42);
271271
}
272+
273+
#[test]
274+
fn uninit_array_index_mut() {
275+
let mut v = MaybeUninit::<[i32; 4]>::uninit();
276+
277+
v[0].write(1);
278+
v[1].write(2);
279+
v[2].write(4);
280+
v[3].write(8);
281+
282+
let v = unsafe { v.assume_init() };
283+
assert_eq!(v, [1, 2, 4, 8]);
284+
}
285+
286+
#[test]
287+
fn uninit_array_as_mut() {
288+
let mut v = MaybeUninit::<[i32; 4]>::uninit();
289+
290+
v.as_mut()[0].write(1);
291+
v.as_mut()[1].write(2);
292+
v.as_mut()[2].write(4);
293+
v.as_mut()[3].write(8);
294+
295+
let v = unsafe { v.assume_init() };
296+
assert_eq!(v, [1, 2, 4, 8]);
297+
}
298+
299+
#[test]
300+
fn uninit_array_loop_init() {
301+
let mut v = MaybeUninit::<[i32; 4]>::uninit();
302+
303+
for v in &mut v {
304+
v.write(42);
305+
}
306+
307+
let v = unsafe { v.assume_init() };
308+
assert_eq!(v, [42, 42, 42, 42]);
309+
}
310+
311+
#[test]
312+
fn uninit_array_iter_mut() {
313+
let mut v = MaybeUninit::<[i32; 4]>::uninit();
314+
315+
v.iter_mut().zip(1..=4).for_each(|(v, val)| {
316+
v.write(val);
317+
});
318+
319+
let v = unsafe { v.assume_init() };
320+
assert_eq!(v, [1, 2, 4, 8]);
321+
}

0 commit comments

Comments
 (0)