Skip to main content

expiring_ref/
lib.rs

1#![no_std]
2#![allow(internal_features)] // only using one for macros
3// The Great Wall Of `expiring_ref`
4#![feature(allocator_api)]
5#![feature(ptr_metadata)]
6#![feature(slice_ptr_get)]
7#![feature(transmute_prefix)]
8#![feature(const_destruct)]
9#![feature(const_trait_impl)]
10#![feature(const_convert)]
11#![feature(arbitrary_self_types)]
12#![feature(unsize)]
13#![feature(coerce_unsized)]
14#![feature(maybe_dangling)]
15#![feature(deref_pure_trait)]
16#![feature(negative_impls)]
17#![feature(const_drop_in_place)]
18#![feature(const_heap)]
19#![feature(const_iter)]
20#![feature(const_manually_drop_take)]
21#![feature(decl_macro)]
22#![feature(const_slice_make_iter)]
23#![feature(sized_type_properties)]
24#![feature(impl_restriction)]
25#![feature(min_specialization)]
26#![feature(fundamental)]
27#![feature(const_clone)]
28#![feature(trusted_random_access)]
29#![feature(allow_internal_unstable)] // this one
30#![feature(const_try)]
31#![feature(rustc_attrs)]
32#![feature(field_projections)]
33
34pub mod iter;
35pub mod traits;
36pub mod macros;
37pub mod unstable;
38
39extern crate alloc;
40
41use crate::traits::{DerefMove, DerefOwn};
42#[cfg(feature = "alloc")]
43use alloc::{boxed::Box, string::String, vec::Vec};
44#[cfg(feature = "alloc")]
45use core::{alloc::Allocator, mem::transmute_prefix as transmute};
46
47use core::marker::{Destruct, Unsize};
48use core::mem::{ManuallyDrop, MaybeDangling, forget};
49use core::ops::{AddAssign, CoerceUnsized, Deref, DerefMut, DerefPure};
50use core::panic::UnwindSafe;
51use core::ptr::NonNull;
52
53// TODO: Solution for field projections please
54/// `&'a own T`, aka an equivalent to C++'s `T&&`
55/// More specifically, this value represents an owned reference which has its contents dropped when it itself is dropped.
56#[repr(transparent)]
57#[fundamental]
58pub struct Own<'a, T: ?Sized + 'a> {
59    inner: &'a mut ManuallyDrop<T>
60}
61
62impl<'a, 'b: 'a, T: ?Sized + 'b> Own<'a, Own<'b, T>> {
63    #[inline]
64    pub fn project_deref(this: Self) -> Own<'a, T> {
65        // SAFETY: this is not used again
66        unsafe { ManuallyDrop::take(Self::into_inner(this)) }
67    }
68}
69
70const impl<'a, T: ?Sized+ 'a> Deref for Own<'a, T> {
71    type Target = T;
72
73    fn deref(&self) -> &Self::Target {
74        &**self.inner
75    }
76}
77
78impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Own<'a, U>> for Own<'b, T> {}
79
80const impl<'a, T: ?Sized> Own<'a, T> {
81    /// SAFETY: Inner must be non-dangling and undropped (is this unsafe tho?)
82    #[inline(always)]
83    pub unsafe fn new(inner: &'a mut ManuallyDrop<T>) -> Self {
84        Self {
85            inner
86        }
87    }
88
89    /// SAFETY: VERY unsafe, `inner` must be FORGOTTEN and UNUSED AFTER THIS.
90    #[inline(always)]
91    pub unsafe fn from_mut(inner: &'a mut T) -> Self {
92        Self {
93            inner: unsafe { transmute(inner) }
94        }
95    }
96
97    //noinspection RsSelfConvention
98    #[inline(always)]
99    pub fn into_inner(this: Self) -> &'a mut ManuallyDrop<T> {
100        // SAFETY: transparent around it :3
101        unsafe { transmute(this) }
102    }
103}
104
105const impl<'a, T: ?Sized> Drop for Own<'a, T> where T: [const] Destruct {
106    fn drop(&mut self) {
107        // SAFETY: this is not exposed elsewhere, it is otherwise undroppable
108        unsafe { ManuallyDrop::drop(self.inner) }
109    }
110}
111
112impl<'a, T: ?Sized> !UnwindSafe for Own<'a, T> {}
113
114const impl<T> DerefMove for Own<'_, T> {
115    fn deref_move(self) -> Self::Target {
116        let mut slot = ManuallyDrop::new(self);
117
118        // SAFETY: for the time of their lifespan, `OwnRef`s point to initialized data
119        unsafe { ManuallyDrop::into_inner(NonNull::from_mut(slot.inner).read()) }
120    }
121}
122
123// SAFETY: `forget_contents` does not drop the `T` instance
124const unsafe impl<T: ?Sized> DerefOwn for Own<'_, T> {
125    unsafe fn deref_own(self: &mut ManuallyDrop<Self>) -> Own<'_, Self::Target> {
126        // SAFETY: caller ensures `self` does not drop its inner value after this
127        unsafe { (&raw const **self).read() }
128    }
129
130    fn forget_contents(this: MaybeDangling<Self>) {
131        forget(this)
132    }
133}
134
135const impl<'a, T: ?Sized> DerefMut for Own<'a, T> {
136    fn deref_mut(&mut self) -> &mut Self::Target {
137        &mut **self.inner
138    }
139}
140
141// SAFETY: `DerefMut` called upon `OwnRef` performs no mutation, only mutable borrowing
142unsafe impl<T: ?Sized> DerefPure for Own<'_, T> {}
143
144//noinspection RsSuperTraitIsNotImplemented
145impl<T: ?Sized> !Copy for Own<'_, T> {}
146
147#[cfg(feature = "alloc")]
148// TODO: remove the where clause if/when Box's Drop impl becomes const
149const unsafe impl<T: ?Sized, A: [const] Allocator> DerefOwn for Box<T, A> where Box<ManuallyDrop<T>, A>: [const] Destruct {
150
151    unsafe fn deref_own(self: &mut ManuallyDrop<Self>) -> Own<'_, Self::Target> {
152        // SAFETY: `self` is inhabited as is ensured by the caller, and ManuallyDrop<T> is transparent around T
153        unsafe { Own::new(transmute(&mut ***self)) }
154    }
155
156    fn forget_contents(this: MaybeDangling<Self>)  {
157        // SAFETY: `MaybeDangling` is transparent around `T`, as is `ManuallyDrop`
158        drop(unsafe { transmute::<_, Box<ManuallyDrop<T>, A>>(this) })
159    }
160}
161
162#[cfg(feature = "alloc")]
163const impl<T> DerefMove for Box<T> where Box<T>: [const] Destruct {
164    fn deref_move(self) -> Self::Target {
165        *self
166    }
167}
168
169#[cfg(feature = "alloc")]
170// TODO: remove the where clause if/when Box's Drop impl becomes const
171const unsafe impl<T, A: [const] Allocator> DerefOwn for Vec<T, A> where Vec<ManuallyDrop<T>, A>: [const] Destruct {
172    unsafe fn deref_own(self: &mut ManuallyDrop<Self>) -> Own<'_, Self::Target> {
173        // SAFETY: `self` is inhabited as is ensured by the caller, and ManuallyDrop<T> is transparent around T
174        unsafe { Own::new(transmute(&mut ***self)) }
175    }
176
177    fn forget_contents(this: MaybeDangling<Self>) {
178        // SAFETY: MaybeDangling<T> is transparent around T, as is ManuallyDrop<T>
179        drop(unsafe { transmute::<_, Vec<ManuallyDrop<T>, A>>(this) });
180    }
181}
182
183#[cfg(feature = "alloc")]
184// TODO: Make const once String has const methods
185unsafe impl DerefOwn for String {
186    unsafe fn deref_own(self: &mut ManuallyDrop<Self>) -> Own<'_, Self::Target> {
187        // SAFETY: `self` is inhabited as is ensured by the caller, and ManuallyDrop<T> is transparent around T
188        unsafe { Own::new(transmute(&mut ***self)) }
189    }
190
191    fn forget_contents(this: MaybeDangling<Self>) {
192        // SAFETY: MaybeDangling<T> is transparent around T, as is ManuallyDrop<T>
193        drop(unsafe { transmute::<_, Vec<ManuallyDrop<u8>>>(this.into_inner().into_bytes()) });
194    }
195}
196
197pub struct DerefOwnGuard<T: DerefOwn>(ManuallyDrop<T>);
198const impl<T: [const] DerefOwn> DerefOwnGuard<T> {
199    pub fn new(inner: T) -> Self {
200        Self(ManuallyDrop::new(inner))
201    }
202
203    pub fn make_own_ref(&mut self) -> Own<'_, <T as Deref>::Target> {
204        // SAFETY: via raii ForgetContents will forget the contents of the container
205        unsafe { self.0.deref_own() }
206    }
207}
208
209const impl<T: [const] DerefOwn> Drop for DerefOwnGuard<T> {
210    fn drop(&mut self) {
211        // SAFETY:
212        unsafe { DerefOwn::forget_contents_in_place(&mut self.0) }
213    }
214}