konst/
manually_drop.rs

1//! Const fn equivalents of [`ManuallyDrop<T>`](core::mem::ManuallyDrop) methods.
2
3use core::mem::ManuallyDrop;
4
5/// Const equivalent of `&*manually_drop`
6///
7/// # Example
8///
9/// ```rust
10/// use std::mem::ManuallyDrop;
11/// use konst::manually_drop;
12///
13/// const FOO: &Foo<u64> = &Foo::new(123456);
14/// const FOO_REF: &u64 = FOO.get();
15/// assert_eq!(FOO.get(), &123456);
16/// assert_eq!(FOO_REF, &123456);
17///
18/// const MD: &ManuallyDrop<u64> = &ManuallyDrop::new(654321);
19/// assert_eq!(manually_drop::as_inner(MD), &654321);
20///
21/// pub struct Foo<T>(ManuallyDrop<T>);
22///
23/// impl<T> Foo<T> {
24///     pub const fn new(value: T) -> Self {
25///         Self(ManuallyDrop::new(value))
26///     }
27///     
28///     pub const fn get(&self) -> &T {
29///         manually_drop::as_inner(&self.0)
30///     }
31/// }
32/// ```
33#[inline(always)]
34pub const fn as_inner<T>(md: &ManuallyDrop<T>) -> &T {
35    // SAFETY: ManuallyDrop<T> is represented the same as T,
36    //         so their pointers should be compatible with an `as` cast
37    unsafe { &*(md as *const ManuallyDrop<T> as *const T) }
38}
39
40/// Const equivalent of `&mut *manually_drop`
41///
42/// # Example
43///
44/// ```rust
45/// use std::mem::ManuallyDrop;
46/// use konst::manually_drop;
47///
48/// const fn add_100(num: &mut u32 ) {
49///     *num += 100;
50/// }
51///
52/// const FOO: ManuallyDrop<u32> = {
53///     let mut mu = ManuallyDrop::new(5);
54///     let inner = manually_drop::as_inner_mut(&mut mu);
55///     add_100(inner);
56///     add_100(inner);
57///     add_100(inner);
58///     mu
59/// };
60///
61/// assert_eq!(*FOO, 305);
62/// ```
63#[cfg(feature = "rust_1_83")]
64#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
65#[inline(always)]
66pub const fn as_inner_mut<T>(md: &mut ManuallyDrop<T>) -> &mut T {
67    // SAFETY: ManuallyDrop<T> is represented the same as T,
68    //         so their pointers should be compatible with an `as` cast
69    unsafe { &mut *(md as *mut ManuallyDrop<T> as *mut T) }
70}
71
72
73
74/// Const equivalent of [`core::mem::ManuallyDrop::take`] with the same safety requirements.
75#[cfg(feature = "rust_1_83")]
76#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
77#[inline(always)]
78pub const unsafe fn take<T>(md: &mut ManuallyDrop<T>) -> T {
79    // SAFETY: ManuallyDrop<T> is represented the same as T,
80    //         so it's valid to read T out of a pointer to ManuallyDrop<T>
81    unsafe { (md as *mut ManuallyDrop<T> as *mut T).read() }
82}