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;