konst/
maybe_uninit.rs

1//! Const fn equivalents of
2//! [`MaybeUninit<T>`](https://doc.rust-lang.org/core/mem/union.MaybeUninit.html) methods.
3
4use core::mem::MaybeUninit;
5
6declare_generic_const! {
7    /// Generic constant for an uninitialized `MaybeUninit<T>`.
8    /// Usable to safely construct a `[MaybeUninit<T>; LEN]` when `T` is non-`Copy`.
9    ///
10    /// As of Rust 1.51.0, `[MaybeUninit::uninit(); LEN]` is not valid for non-`Copy` types,
11    /// but `[CONST; LEN]` does work, like in the example below.
12    ///
13    /// # Example
14    ///
15    /// ```rust
16    /// use konst::maybe_uninit::UNINIT;
17    ///
18    /// use std::mem::{self, MaybeUninit};
19    ///
20    /// // Intentionally doesn't implement `Copy`
21    /// #[derive(Debug, PartialEq, Eq, Clone)]
22    /// struct NonCopy(u8);
23    ///
24    /// const INITS: [NonCopy; 5] = {
25    ///     let mut uninits = [UNINIT::<NonCopy>::V; 5];
26    ///     konst::for_range!{i in 0..5=>
27    ///         uninits[i] = MaybeUninit::new(NonCopy(i as u8 * 3));
28    ///     }
29    ///     unsafe{ mem::transmute(uninits) }
30    /// };
31    ///
32    /// assert_eq!(INITS, [NonCopy(0), NonCopy(3), NonCopy(6), NonCopy(9), NonCopy(12)]);
33    ///
34    for[T]
35    pub const UNINIT[T]: MaybeUninit<T> = MaybeUninit::uninit();
36}
37
38#[cfg(feature = "rust_1_51")]
39declare_generic_const! {
40    /// Generic constant for an uninitialized `[MaybeUninit<T>; N]`. Requires Rust 1.51.0.
41    ///
42    /// # Features
43    ///
44    /// This requires the "rust_1_51" feature, which requires Rust 1.51.0.
45    ///
46    /// # Example
47    ///
48    /// ```rust
49    /// use konst::maybe_uninit::UNINIT_ARRAY;
50    ///
51    /// use std::mem::{self, MaybeUninit};
52    ///
53    /// const INITS: [[u8; 2]; 2] = {
54    ///     let mut uninits = [UNINIT_ARRAY::<u8, 2>::V; 2];
55    ///
56    ///     uninits[0] = [MaybeUninit::new(3), MaybeUninit::new(5)];
57    ///     uninits[1] = [MaybeUninit::new(8), MaybeUninit::new(13)];
58    ///
59    ///     unsafe{ mem::transmute(uninits) }
60    /// };
61    ///
62    /// assert_eq!(INITS, [[3, 5], [8, 13]]);
63    /// ```
64    #[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_51")))]
65    for[T, const N: usize]
66    pub const UNINIT_ARRAY[T; N]: [MaybeUninit<T>; N] = [UNINIT::V; N];
67}
68
69/// Const equivalent of [`MaybeUninit::uninit_array`](core::mem::MaybeUninit::uninit_array)
70///
71/// # Example
72///
73/// ```rust
74/// use konst::maybe_uninit as mu;
75///
76/// use std::mem::{self, MaybeUninit};
77///
78/// const INITS: [u8; 2] = {
79///     let mut uninits = mu::uninit_array::<u8, 2>();
80///
81///     uninits[0] = MaybeUninit::new(21);
82///     uninits[1] = MaybeUninit::new(34);
83///
84///     unsafe{ mu::array_assume_init(uninits) }
85/// };
86///
87/// assert_eq!(INITS, [21, 34]);
88/// ```
89#[cfg(feature = "rust_1_56")]
90#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_56")))]
91pub use konst_macro_rules::utils_1_56::uninit_array;
92
93/// Const equivalent of [`MaybeUninit::assume_init`](core::mem::MaybeUninit::assume_init)
94///
95/// # Safety
96///
97/// This has [the same safety requirements as `MaybeUninit::assume_init`
98/// ](https://doc.rust-lang.org/1.55.0/core/mem/union.MaybeUninit.html#safety)
99///
100/// # Example
101///
102/// ```rust
103/// use std::mem::MaybeUninit;
104///
105/// use konst::maybe_uninit;
106///
107/// const MU: MaybeUninit<u16> = MaybeUninit::new(12345);
108/// const INIT: u16 = unsafe{ maybe_uninit::assume_init(MU) };
109///
110/// assert_eq!(INIT, 12345);
111///
112/// ```
113#[cfg(feature = "rust_1_56")]
114#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_56")))]
115#[inline(always)]
116pub const unsafe fn assume_init<T>(md: MaybeUninit<T>) -> T {
117    crate::utils_1_56::__priv_transmute! {MaybeUninit<T>, T, md}
118}
119
120/// Const equivalent of [`MaybeUninit::assume_init_ref`](core::mem::MaybeUninit::assume_init_ref)
121///
122/// # Safety
123///
124/// This has [the same safety requirements as `MaybeUninit::assume_init_ref`
125/// ](https://doc.rust-lang.org/1.55.0/core/mem/union.MaybeUninit.html#safety-3)
126///
127/// # Example
128///
129/// ```rust
130/// use std::cmp::Ordering;
131/// use std::mem::MaybeUninit;
132///
133/// use konst::maybe_uninit;
134///
135/// const MU: &MaybeUninit<Ordering> = &MaybeUninit::new(Ordering::Greater);
136/// const INIT: &Ordering = unsafe{ maybe_uninit::assume_init_ref(MU) };
137///
138/// assert_eq!(INIT, &Ordering::Greater);
139///
140/// ```
141#[cfg(feature = "rust_1_56")]
142#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_56")))]
143#[inline(always)]
144pub const unsafe fn assume_init_ref<T>(md: &MaybeUninit<T>) -> &T {
145    crate::utils_1_56::__priv_transmute_ref! {MaybeUninit<T>, T, md}
146}
147
148/// Const equivalent of [`MaybeUninit::assume_init_mut`](core::mem::MaybeUninit::assume_init_mut)
149///
150/// # Safety
151///
152/// This has [the same safety requirements as `MaybeUninit::assume_init_mut`
153/// ](https://doc.rust-lang.org/1.55.0/core/mem/union.MaybeUninit.html#safety-3)
154///
155/// # Example
156///
157/// ```rust
158/// # #![feature(const_mut_refs)]
159/// use std::cmp::Ordering;
160/// use std::mem::MaybeUninit;
161///
162/// use konst::maybe_uninit;
163///
164/// const unsafe fn mutate_mu(mu: &mut MaybeUninit<u32>) -> u32 {
165///     let mutref = maybe_uninit::assume_init_mut(mu);
166///     *mutref += 100;
167///     *mutref
168/// }
169///
170/// const MU: (MaybeUninit<u32>, [u32; 3]) = {
171///     let mut mu = MaybeUninit::new(5);
172///     let array = unsafe{
173///         [mutate_mu(&mut mu), mutate_mu(&mut mu), mutate_mu(&mut mu)]
174///     };
175///     (mu, array)
176/// };
177///
178/// unsafe{ assert_eq!(MU.0.assume_init(), 305); }
179/// assert_eq!(MU.1, [105, 205, 305]);
180///
181/// ```
182#[cfg(feature = "mut_refs")]
183#[cfg_attr(feature = "docsrs", doc(cfg(feature = "mut_refs")))]
184#[inline(always)]
185pub const unsafe fn assume_init_mut<T>(md: &mut MaybeUninit<T>) -> &mut T {
186    crate::utils_mut::__priv_transmute_mut! {MaybeUninit<T>, T, md}
187}
188
189/// Const equivalent of [`MaybeUninit::write`](core::mem::MaybeUninit::write)
190///
191/// # Example
192///
193/// ```rust
194/// # #![feature(const_mut_refs)]
195/// use std::cmp::Ordering;
196/// use std::mem::MaybeUninit;
197///
198/// use konst::maybe_uninit;
199///
200/// const fn cond_init(mu: &mut MaybeUninit<u32>, value: u32) -> Option<&mut u32> {
201///     if value % 3 != 0 {
202///         Some(maybe_uninit::write(mu, value))
203///     } else {
204///         None
205///     }
206/// }
207///
208/// let mut mu = MaybeUninit::uninit();
209/// assert_eq!(cond_init(&mut mu, 0), None);
210/// assert_eq!(cond_init(&mut mu, 1), Some(&mut 1));
211/// assert_eq!(cond_init(&mut mu, 2), Some(&mut 2));
212/// assert_eq!(cond_init(&mut mu, 3), None);
213/// assert_eq!(cond_init(&mut mu, 4), Some(&mut 4));
214/// assert_eq!(cond_init(&mut mu, 5), Some(&mut 5));
215/// assert_eq!(cond_init(&mut mu, 6), None);
216///
217/// ```
218#[cfg(feature = "mut_refs")]
219#[cfg_attr(feature = "docsrs", doc(cfg(feature = "mut_refs")))]
220#[inline(always)]
221pub const fn write<T>(md: &mut MaybeUninit<T>, value: T) -> &mut T {
222    *md = MaybeUninit::new(value);
223    unsafe {
224        crate::utils_mut::__priv_transmute_mut! {MaybeUninit<T>, T, md}
225    }
226}
227
228/// Const equivalent of [`MaybeUninit::as_ptr`](core::mem::MaybeUninit::as_ptr)
229///
230/// # Example
231///
232/// ```rust
233/// use std::mem::MaybeUninit;
234///
235/// use konst::maybe_uninit;
236///
237/// const MU: &MaybeUninit<Option<&str>> = &MaybeUninit::new(Some("foo"));
238/// const PTR: *const Option<&str> = maybe_uninit::as_ptr(MU);
239///
240/// unsafe {
241///     assert_eq!(*PTR, Some("foo"));
242/// }
243///
244/// ```
245#[inline(always)]
246pub const fn as_ptr<T>(md: &MaybeUninit<T>) -> *const T {
247    md as *const MaybeUninit<T> as *const T
248}
249
250/// Const equivalent of [`MaybeUninit::as_mut_ptr`].
251///
252/// # Example
253///
254/// Initializing a `#[repr(u8)]` enum
255///
256/// ```rust
257/// # #![feature(const_mut_refs)]
258/// use std::mem::MaybeUninit;
259///
260/// use konst::{maybe_uninit as mu, ptr};
261///
262/// const ENUM: Enum = {
263///     let mut mu = MaybeUninit::<Enum>::uninit();
264///     
265///     let ptr = mu::as_mut_ptr(&mut mu).cast::<MaybeUninit<Discr>>();
266///     unsafe{
267///         *ptr::deref_mut(ptr) = MaybeUninit::new(Discr::Bar);
268///         mu::assume_init(mu)
269///     }
270/// };
271///
272/// unsafe {
273///     assert_eq!(ENUM, Enum::Bar);
274/// }
275///
276/// #[repr(u8)]
277/// enum Discr {
278///     Foo,
279///     Bar,
280///     Baz,
281/// }
282///
283/// #[repr(u8)]
284/// #[derive(Debug, PartialEq)]
285/// enum Enum {
286///     Foo(u8),
287///     Bar,
288///     Baz{s: String},
289/// }
290///
291/// ```
292///
293/// [`MaybeUninit::as_mut_ptr`]:
294/// https://doc.rust-lang.org/nightly/core/mem/union.MaybeUninit.html#method.as_ptr
295#[cfg(feature = "mut_refs")]
296#[cfg_attr(feature = "docsrs", doc(cfg(feature = "mut_refs")))]
297#[inline(always)]
298pub const fn as_mut_ptr<T>(md: &mut MaybeUninit<T>) -> *mut T {
299    md as *mut MaybeUninit<T> as *mut T
300}
301
302/// Const equivalent of
303/// [`MaybeUninit::array_assume_init`](core::mem::MaybeUninit::array_assume_init)
304///
305/// # Safety
306///
307/// This has [the same safety requirements as `MaybeUninit::array_assume_init`
308/// ](https://doc.rust-lang.org/1.55.0/core/mem/union.MaybeUninit.html#safety-5)
309///
310/// # Example
311///
312/// ```rust
313/// use std::mem::MaybeUninit;
314///
315/// use konst::maybe_uninit;
316///
317/// const INIT: [u16; 10] = {
318///     let mut arr: [MaybeUninit<u16>; 10] = maybe_uninit::UNINIT_ARRAY::V;
319///
320///     let mut i = 0usize;
321///     while i < 10 {
322///         let x = (i as u16) + 1;
323///         arr[i as usize] = MaybeUninit::new(x * x);
324///         i += 1;
325///     }
326///
327///     unsafe{ maybe_uninit::array_assume_init(arr) }
328/// };
329///
330/// assert_eq!(INIT, [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]);
331///
332/// ```
333#[cfg(feature = "rust_1_56")]
334#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_56")))]
335pub use konst_macro_rules::utils_1_56::array_assume_init;