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;