|
3 | 3 | #![warn(missing_docs)]
|
4 | 4 |
|
5 | 5 | use core::{
|
6 |
| - cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit, num::NonZeroUsize, ptr::NonNull, |
| 6 | + cell::UnsafeCell, marker::PhantomData, mem::ManuallyDrop, num::NonZeroUsize, ptr::NonNull, |
7 | 7 | };
|
8 | 8 |
|
9 | 9 | /// Type-erased borrow of some unknown type chosen when constructing this type.
|
@@ -98,6 +98,9 @@ macro_rules! impl_ptr {
|
98 | 98 | }
|
99 | 99 |
|
100 | 100 | impl_ptr!(Ptr);
|
| 101 | +impl_ptr!(PtrMut); |
| 102 | +impl_ptr!(OwningPtr); |
| 103 | + |
101 | 104 | impl<'a> Ptr<'a> {
|
102 | 105 | /// Transforms this [`Ptr`] into an [`PtrMut`]
|
103 | 106 | ///
|
@@ -127,7 +130,16 @@ impl<'a> Ptr<'a> {
|
127 | 130 | self.0.as_ptr()
|
128 | 131 | }
|
129 | 132 | }
|
130 |
| -impl_ptr!(PtrMut); |
| 133 | + |
| 134 | +impl<'a, T> From<&'a T> for Ptr<'a> { |
| 135 | + #[inline] |
| 136 | + fn from(val: &'a T) -> Self { |
| 137 | + // SAFETY: The returned pointer has the same lifetime as the passed reference. |
| 138 | + // Access is immutable. |
| 139 | + unsafe { Self::new(NonNull::from(val).cast()) } |
| 140 | + } |
| 141 | +} |
| 142 | + |
131 | 143 | impl<'a> PtrMut<'a> {
|
132 | 144 | /// Transforms this [`PtrMut`] into an [`OwningPtr`]
|
133 | 145 | ///
|
@@ -157,15 +169,24 @@ impl<'a> PtrMut<'a> {
|
157 | 169 | self.0.as_ptr()
|
158 | 170 | }
|
159 | 171 | }
|
160 |
| -impl_ptr!(OwningPtr); |
| 172 | + |
| 173 | +impl<'a, T> From<&'a mut T> for PtrMut<'a> { |
| 174 | + #[inline] |
| 175 | + fn from(val: &'a mut T) -> Self { |
| 176 | + // SAFETY: The returned pointer has the same lifetime as the passed reference. |
| 177 | + // The reference is mutable, and thus will not alias. |
| 178 | + unsafe { Self::new(NonNull::from(val).cast()) } |
| 179 | + } |
| 180 | +} |
| 181 | + |
161 | 182 | impl<'a> OwningPtr<'a> {
|
162 | 183 | /// Consumes a value and creates an [`OwningPtr`] to it while ensuring a double drop does not happen.
|
163 | 184 | #[inline]
|
164 | 185 | pub fn make<T, F: FnOnce(OwningPtr<'_>) -> R, R>(val: T, f: F) -> R {
|
165 |
| - let mut temp = MaybeUninit::new(val); |
166 |
| - // SAFETY: `temp.as_mut_ptr()` is a reference to a local value on the stack, so it cannot be null |
167 |
| - let ptr = unsafe { NonNull::new_unchecked(temp.as_mut_ptr().cast::<u8>()) }; |
168 |
| - f(Self(ptr, PhantomData)) |
| 186 | + let mut temp = ManuallyDrop::new(val); |
| 187 | + // SAFETY: The value behind the pointer will not get dropped or observed later, |
| 188 | + // so it's safe to promote it to an owning pointer. |
| 189 | + f(unsafe { PtrMut::from(&mut *temp).promote() }) |
169 | 190 | }
|
170 | 191 |
|
171 | 192 | /// Consumes the [`OwningPtr`] to obtain ownership of the underlying data of type `T`.
|
|
0 commit comments