konst/maybe_uninit.rs
1//! Const fn equivalents of
2//! [`MaybeUninit<T>`](https://doc.rust-lang.org/core/mem/union.MaybeUninit.html) methods.
3//!
4//! # Removed in 0.3.0
5//!
6//! These functions were removed in 0.3.0 because there is an equivalent
7//! const fn in the standard library:
8//!
9//! - `as_ptr`: [`MaybeUninit::as_ptr`]
10//! - `assume_init`: [`MaybeUninit::assume_init`]
11//! - `assume_init_ref`: [`MaybeUninit::assume_init_ref`]
12//!
13//!
14
15use core::mem::MaybeUninit;
16
17declare_generic_const! {
18 /// Generic constant for an uninitialized `MaybeUninit<T>`.
19 /// Usable to safely construct a `[MaybeUninit<T>; LEN]` when `T` is non-`Copy`.
20 ///
21 /// As of Rust 1.65.0, `[MaybeUninit::uninit(); LEN]` is not valid for non-`Copy` types,
22 /// but `[CONST; LEN]` does work, like in the example below.
23 ///
24 /// # Example
25 ///
26 /// ```rust
27 /// use konst::maybe_uninit::{self as mu, UNINIT};
28 ///
29 /// use std::mem::{self, MaybeUninit};
30 ///
31 /// // Intentionally doesn't implement `Copy`
32 /// #[derive(Debug, PartialEq, Eq, Clone)]
33 /// struct NonCopy(u8);
34 ///
35 /// const INITS: [NonCopy; 5] = {
36 /// let mut uninits = [UNINIT::<NonCopy>::V; 5];
37 /// konst::for_range!{i in 0..5=>
38 /// uninits[i] = MaybeUninit::new(NonCopy(i as u8 * 3));
39 /// }
40 /// unsafe{ mu::array_assume_init(uninits) }
41 /// };
42 ///
43 /// assert_eq!(INITS, [NonCopy(0), NonCopy(3), NonCopy(6), NonCopy(9), NonCopy(12)]);
44 ///
45 for[T]
46 pub const UNINIT[T]: MaybeUninit<T> = MaybeUninit::uninit();
47}
48
49declare_generic_const! {
50 /// Generic constant for an uninitialized `[MaybeUninit<T>; N]`.
51 ///
52 /// # Example
53 ///
54 /// ```rust
55 /// use konst::maybe_uninit::UNINIT_ARRAY;
56 ///
57 /// use std::mem::{self, MaybeUninit};
58 ///
59 /// const INITS: [[u8; 2]; 2] = {
60 /// let mut uninits: [[MaybeUninit<u8>; 2]; 2] = [UNINIT_ARRAY::<u8, 2>::V; 2];
61 ///
62 /// uninits[0] = [MaybeUninit::new(3), MaybeUninit::new(5)];
63 /// uninits[1] = [MaybeUninit::new(8), MaybeUninit::new(13)];
64 ///
65 /// unsafe{ mem::transmute(uninits) }
66 /// };
67 ///
68 /// assert_eq!(INITS, [[3, 5], [8, 13]]);
69 /// ```
70 for[T, const N: usize]
71 pub const UNINIT_ARRAY[T; N]: [MaybeUninit<T>; N] = [UNINIT::V; N];
72}
73
74/// Const equivalent of [`MaybeUninit::uninit_array`](core::mem::MaybeUninit::uninit_array)
75///
76/// # Example
77///
78/// ```rust
79/// use konst::maybe_uninit as mu;
80///
81/// use std::mem::{self, MaybeUninit};
82///
83/// const INITS: [u8; 2] = {
84/// let mut uninits = mu::uninit_array::<u8, 2>();
85///
86/// uninits[0] = MaybeUninit::new(21);
87/// uninits[1] = MaybeUninit::new(34);
88///
89/// unsafe{ mu::array_assume_init(uninits) }
90/// };
91///
92/// assert_eq!(INITS, [21, 34]);
93/// ```
94pub use konst_kernel::maybe_uninit::uninit_array;
95
96/// Const equivalent of [`MaybeUninit::assume_init_mut`](core::mem::MaybeUninit::assume_init_mut)
97///
98/// # Safety
99///
100/// This has [the same safety requirements as `MaybeUninit::assume_init_mut`
101/// ](https://doc.rust-lang.org/1.55.0/core/mem/union.MaybeUninit.html#safety-3)
102///
103/// # Example
104///
105/// ```rust
106/// use std::cmp::Ordering;
107/// use std::mem::MaybeUninit;
108///
109/// use konst::maybe_uninit;
110///
111/// const unsafe fn mutate_mu(mu: &mut MaybeUninit<u32>) -> u32 {
112/// let mutref = maybe_uninit::assume_init_mut(mu);
113/// *mutref += 100;
114/// *mutref
115/// }
116///
117/// const MU: (MaybeUninit<u32>, [u32; 3]) = {
118/// let mut mu = MaybeUninit::new(5);
119/// let array = unsafe{
120/// [mutate_mu(&mut mu), mutate_mu(&mut mu), mutate_mu(&mut mu)]
121/// };
122/// (mu, array)
123/// };
124///
125/// unsafe{ assert_eq!(MU.0.assume_init(), 305); }
126/// assert_eq!(MU.1, [105, 205, 305]);
127///
128/// ```
129#[cfg(feature = "rust_1_83")]
130#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
131#[inline(always)]
132pub const unsafe fn assume_init_mut<T>(md: &mut MaybeUninit<T>) -> &mut T {
133 &mut *(md as *mut MaybeUninit<T> as *mut T)
134}
135
136/// Const equivalent of [`MaybeUninit::write`](core::mem::MaybeUninit::write)
137///
138/// # Example
139///
140/// ```rust
141/// use std::cmp::Ordering;
142/// use std::mem::MaybeUninit;
143///
144/// use konst::maybe_uninit;
145///
146/// const fn cond_init(mu: &mut MaybeUninit<u32>, value: u32) -> Option<&mut u32> {
147/// if value % 3 != 0 {
148/// Some(maybe_uninit::write(mu, value))
149/// } else {
150/// None
151/// }
152/// }
153///
154/// let mut mu = MaybeUninit::uninit();
155/// assert_eq!(cond_init(&mut mu, 0), None);
156/// assert_eq!(cond_init(&mut mu, 1), Some(&mut 1));
157/// assert_eq!(cond_init(&mut mu, 2), Some(&mut 2));
158/// assert_eq!(cond_init(&mut mu, 3), None);
159/// assert_eq!(cond_init(&mut mu, 4), Some(&mut 4));
160/// assert_eq!(cond_init(&mut mu, 5), Some(&mut 5));
161/// assert_eq!(cond_init(&mut mu, 6), None);
162///
163/// ```
164#[cfg(feature = "rust_1_83")]
165#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
166#[inline(always)]
167pub const fn write<T>(md: &mut MaybeUninit<T>, value: T) -> &mut T {
168 *md = MaybeUninit::new(value);
169 unsafe { &mut *(md as *mut MaybeUninit<T> as *mut T) }
170}
171
172/// Const equivalent of [`MaybeUninit::as_mut_ptr`].
173///
174/// # Const stabilization
175///
176/// The equivalent std function was const-stabilized in Rust 1.83.0.
177///
178/// # Example
179///
180/// Initializing a `#[repr(u8)]` enum
181///
182/// ```rust
183/// use std::mem::MaybeUninit;
184///
185/// use konst::maybe_uninit as mu;
186///
187/// const ENUM: Enum = {
188/// let mut mu = MaybeUninit::<Enum>::uninit();
189///
190/// let ptr = mu::as_mut_ptr(&mut mu).cast::<MaybeUninit<Discr>>();
191/// unsafe{
192/// *ptr = MaybeUninit::new(Discr::Bar);
193/// mu.assume_init()
194/// }
195/// };
196///
197/// unsafe {
198/// assert_eq!(ENUM, Enum::Bar);
199/// }
200///
201/// #[repr(u8)]
202/// enum Discr {
203/// Foo,
204/// Bar,
205/// Baz,
206/// }
207///
208/// #[repr(u8)]
209/// #[derive(Debug, PartialEq)]
210/// enum Enum {
211/// Foo(u8),
212/// Bar,
213/// Baz{s: String},
214/// }
215///
216/// ```
217///
218/// [`MaybeUninit::as_mut_ptr`]:
219/// https://doc.rust-lang.org/core/mem/union.MaybeUninit.html#method.as_mut_ptr
220#[cfg(feature = "rust_1_83")]
221#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
222#[inline(always)]
223pub const fn as_mut_ptr<T>(md: &mut MaybeUninit<T>) -> *mut T {
224 md as *mut MaybeUninit<T> as *mut T
225}
226
227/// Const equivalent of
228/// [`MaybeUninit::array_assume_init`](core::mem::MaybeUninit::array_assume_init)
229///
230/// # Safety
231///
232/// This has [the same safety requirements as `MaybeUninit::array_assume_init`
233/// ](https://doc.rust-lang.org/1.55.0/core/mem/union.MaybeUninit.html#safety-5)
234///
235/// # Example
236///
237/// ```rust
238/// use std::mem::MaybeUninit;
239///
240/// use konst::maybe_uninit;
241///
242/// const INIT: [u16; 10] = {
243/// let mut arr: [MaybeUninit<u16>; 10] = maybe_uninit::UNINIT_ARRAY::V;
244///
245/// let mut i = 0usize;
246/// while i < 10 {
247/// let x = (i as u16) + 1;
248/// arr[i as usize] = MaybeUninit::new(x * x);
249/// i += 1;
250/// }
251///
252/// unsafe{ maybe_uninit::array_assume_init(arr) }
253/// };
254///
255/// assert_eq!(INIT, [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]);
256///
257/// ```
258pub use konst_kernel::maybe_uninit::array_assume_init;