expiring_ref 0.5.6

A crate designed to implement a mechanism for owning values, via a destructively-moved equivalent to C++'s xvalues/`T&&`
Documentation
#![feature(allocator_api)]
#![feature(ptr_metadata)]
#![feature(slice_ptr_get)]
#![feature(transmute_prefix)]
#![feature(const_destruct)]
#![feature(const_trait_impl)]
#![feature(const_convert)]
#![feature(arbitrary_self_types)]
#![feature(unsize)]
#![feature(coerce_unsized)]
#![feature(maybe_dangling)]
#![feature(deref_pure_trait)]
#![feature(negative_impls)]
#![feature(super_let)]
#![feature(const_drop_in_place)]
#![feature(const_heap)]
#![feature(const_iter)]
#![feature(temporary_niche_types)]
#![no_std]

#![feature(const_manually_drop_take)]
#![feature(decl_macro)]
#![feature(const_slice_make_iter)]
#![feature(sized_type_properties)]

pub mod iter;

extern crate alloc;

use alloc::alloc::{Global, handle_alloc_error};
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use core::alloc::{Allocator, Layout};
use core::marker::{Destruct, PhantomData, Unsize};
use core::mem::{ManuallyDrop, MaybeDangling, MaybeUninit, forget, transmute_prefix as transmute, transmute_prefix};
use core::num::niche_types::UsizeNoHighBit;
use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure};
use core::panic::{RefUnwindSafe, UnwindSafe};
use core::ptr::{NonNull, metadata};
use core::ptr;
use core::slice::{Iter, IterMut};

#[macro_export]
macro_rules! own {
    ($e:expr) => {
        {
            super let mut _TEMP = ::core::mem::ManuallyDrop::new($e);
            // SAFETY: value is always inhabited
            unsafe { $crate::OwnRef::new(&mut _TEMP) }
        }
    };
}

pub macro deref_own {
    ($e:expr) => {
        {
            super let mut __FORGET = $crate::ForgetContents::new($e);
            __FORGET.make_own_ref()
        }
    },
}

pub struct OwnRef<'a, T: ?Sized + 'a> {
    inner: &'a mut ManuallyDrop<T>
}

const impl<'a, T: ?Sized+ 'a> Deref for OwnRef<'a, T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &**self.inner
    }
}

impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<OwnRef<'a, U>> for OwnRef<'b, T> {}

const impl<'a, T: ?Sized> OwnRef<'a, T> {
    // SAFETY: Inner must be non-dangling and undropped (is this unsafe tho?)
    #[inline(always)]
    pub unsafe fn new(inner: &'a mut ManuallyDrop<T>) -> Self {
        Self {
            inner
        }
    }
}

const impl<'a, T: ?Sized> Drop for OwnRef<'a, T> where T: [const] Destruct {
    fn drop(&mut self) {
        // SAFETY: this is not exposed elsewhere, it is otherwise undroppable
        unsafe { ManuallyDrop::drop(self.inner) }
    }
}

pub const trait DerefMove: DerefMut<Target: Sized> {
    fn deref_move(self) -> Self::Target;
}
// SAFETY: `forget_contents` MUST handle the MaybeDangling instance and ensure the inner value is NOT DROPPED.
pub const unsafe trait DerefOwn: DerefMut {
    // TODO: by the specification of ManuallyDrop, it must have a value.... so yeah
    // SAFETY: self MUST have a value and MUST have `forget_contents` called on it if the return of this function is moved from or dropped
    unsafe fn deref_own(self: &mut ManuallyDrop<Self>) -> OwnRef<'_, Self::Target>;

    fn forget_contents(this: MaybeDangling<Self>);

    // SAFETY: `this` must not be used again.
    unsafe fn forget_contents_in_place(this: &mut ManuallyDrop<Self>) where Self: Sized {
        // SAFETY: `this` is not used again and MaybeDangling<T> is transparent around T
        unsafe {
            Self::forget_contents(transmute_prefix(ManuallyDrop::take(this)))
        }
    }
}

impl<'a, T: ?Sized> !UnwindSafe for OwnRef<'a, T> {}

const impl<T> DerefMove for OwnRef<'_, T> {
    fn deref_move(self) -> Self::Target {
        let mut slot = ManuallyDrop::new(self);

        // SAFETY: for the time of their lifespan, `OwnRef`s point to initialized data
        unsafe { ManuallyDrop::into_inner(NonNull::from_mut(slot.inner).read()) }
    }
}
// SAFETY: `forget_contents` does not drop the `T` instance
const unsafe impl<T: ?Sized> DerefOwn for OwnRef<'_, T> {
    unsafe fn deref_own(self: &mut ManuallyDrop<Self>) -> OwnRef<'_, Self::Target> {
        // SAFETY: caller ensures `self` does not drop its inner value after this
        unsafe { (&raw const **self).read() }
    }

    fn forget_contents(this: MaybeDangling<Self>) {
        forget(this)
    }
}

const impl<'a, T: ?Sized> DerefMut for OwnRef<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut **self.inner
    }
}

// SAFETY: `DerefMut` called upon `OwnRef` performs no mutation, only mutable borrowing
unsafe impl<T: ?Sized> DerefPure for OwnRef<'_, T> {}

//noinspection RsSuperTraitIsNotImplemented
impl<T: ?Sized> !Copy for OwnRef<'_, T> {}

// TODO: remove the where clause if/when Box's Drop impl becomes const
const unsafe impl<T: ?Sized, A: [const] Allocator> DerefOwn for Box<T, A> where Box<ManuallyDrop<T>, A>: [const] Destruct {

    unsafe fn deref_own(self: &mut ManuallyDrop<Self>) -> OwnRef<'_, Self::Target> {
        // SAFETY: `self` is inhabited as is ensured by the caller, and ManuallyDrop<T> is transparent around T
        unsafe { OwnRef::new(transmute_prefix(&mut ***self)) }
    }

    fn forget_contents(this: MaybeDangling<Self>)  {
        // SAFETY: `MaybeDangling` is transparent around `T`, as is `ManuallyDrop`
        drop(unsafe { transmute_prefix::<_, Box<ManuallyDrop<T>, A>>(this) })
    }
}

const impl<T> DerefMove for Box<T> where Box<T>: [const] Destruct {
    fn deref_move(self) -> Self::Target {
        *self
    }
}

// TODO: remove the where clause if/when Box's Drop impl becomes const
const unsafe impl<T, A: [const] Allocator> DerefOwn for Vec<T, A> where Vec<ManuallyDrop<T>, A>: [const] Destruct {
    unsafe fn deref_own(self: &mut ManuallyDrop<Self>) -> OwnRef<'_, Self::Target> {
        // SAFETY: `self` is inhabited as is ensured by the caller, and ManuallyDrop<T> is transparent around T
        unsafe { OwnRef::new(transmute_prefix(&mut ***self)) }
    }

    fn forget_contents(this: MaybeDangling<Self>) {
        // SAFETY: MaybeDangling<T> is transparent around T, as is ManuallyDrop<T>
        drop(unsafe { transmute_prefix::<_, Vec<ManuallyDrop<T>, A>>(this) });
    }
}

// TODO: Make const once String has const methods
unsafe impl DerefOwn for String {
    unsafe fn deref_own(self: &mut ManuallyDrop<Self>) -> OwnRef<'_, Self::Target> {
        // SAFETY: `self` is inhabited as is ensured by the caller, and ManuallyDrop<T> is transparent around T
        unsafe { OwnRef::new(transmute_prefix(&mut ***self)) }
    }

    fn forget_contents(this: MaybeDangling<Self>) {
        // SAFETY: MaybeDangling<T> is transparent around T, as is ManuallyDrop<T>
        drop(unsafe { transmute_prefix::<_, Vec<ManuallyDrop<u8>>>(this.into_inner().into_bytes()) });
    }
}

/// Values which may take a value and put it into an allocation.
pub trait Take<T: ?Sized> {
    /// Move the value into a new allocation.
    fn take(val: OwnRef<T>) -> Self;
}

/// Values which may take a value and put it into an allocation, given a specified allocator.
pub trait TakeIn<T: ?Sized, A: Allocator> {
    /// Move the value into a new allocation given the specified allocator.
    fn take_in(val: OwnRef<T>, alloc: A) -> Self;
}

impl<T: Sized> Take<T> for T {
    #[inline(always)]
    fn take(val: OwnRef<T>) -> Self {
        val.deref_move()
    }
}

impl<T: ?Sized> Take<T> for Box<T> {
    #[inline(always)]
    fn take(val: OwnRef<T>) -> Self {
        Self::take_in(val, Global)
    }
}

impl<T: ?Sized, A: Allocator> TakeIn<T, A> for Box<T, A> {
    #[inline(always)]
    fn take_in(val: OwnRef<T>, alloc: A) -> Self {
        let val = MaybeDangling::new(val);
        let borrow = &**val.as_ref();
        let meta = metadata(borrow);
        let layout = Layout::for_value(borrow);
        let this_ptr = match alloc.allocate(layout) {
            Ok(m) => NonNull::<T>::from_raw_parts(m.as_non_null_ptr(), meta),
            Err(_) => handle_alloc_error(layout),
        };
        // SAFETY: The inner value is not moved nor dropped after this read
        unsafe { ptr::copy_nonoverlapping((borrow as *const T).cast::<u8>(), this_ptr.cast().as_ptr(), layout.size()); }

        DerefOwn::forget_contents(val);
        // SAFETY: `this` has been inhabited with a value
        unsafe { Box::from_raw_in(this_ptr.as_ptr(), alloc) }
    }
}

impl<T: Sized> Take<[T]> for Vec<T> {
    #[inline(always)]
    fn take(val: OwnRef<[T]>) -> Self {
        let val = MaybeDangling::new(val);
        let borrow = &**val.as_ref();
        let len = borrow.len();
        let mut this: Vec<MaybeUninit<T>> = Box::new_uninit_slice(len).into_vec();
        let this_ptr = this[0].as_mut_ptr();
        // SAFETY: The value is not moved nor dropped after this read
        unsafe { ptr::copy_nonoverlapping(&raw const borrow[0], this_ptr, len); }
        DerefOwn::forget_contents(val);
        // SAFETY: `this` has been inhabited with a value
        unsafe { transmute(this) }
    }
}

impl<T: Sized, A: Allocator> TakeIn<[T], A> for Vec<T, A> {
    #[inline(always)]
    fn take_in(val: OwnRef<[T]>, alloc: A) -> Self {
        let val = MaybeDangling::new(val);
        let borrow = &**val.as_ref();
        let len = borrow.len();
        let mut this: Vec<MaybeUninit<T>, A> = Box::new_uninit_slice_in(len, alloc).into_vec();
        let this_ptr = this[0].as_mut_ptr();
        // SAFETY: The value is not moved nor dropped after this read
        unsafe { ptr::copy_nonoverlapping(&raw const borrow[0], this_ptr, len); }
        DerefOwn::forget_contents(val);
        // SAFETY: `this` has been inhabited with a value
        unsafe { transmute(this) }
    }
}

pub struct ForgetContents<T: DerefOwn>(ManuallyDrop<T>);
const impl<T: [const] DerefOwn> ForgetContents<T> {
    pub fn new(inner: T) -> Self {
        Self(ManuallyDrop::new(inner))
    }

    pub fn make_own_ref(&mut self) -> OwnRef<'_, <T as Deref>::Target> {
        // SAFETY: via raii ForgetContents will forget the contents of the container
        unsafe { self.0.deref_own() }
    }
}

const impl<T: [const] DerefOwn> Drop for ForgetContents<T> {
    fn drop(&mut self) {
        // SAFETY:
        unsafe { DerefOwn::forget_contents_in_place(&mut self.0) }
    }
}

impl Take<str> for String {
    #[inline(always)]
    fn take(val: OwnRef<str>) -> Self {
        let val = MaybeDangling::new(val);
        let borrow = &**val.as_ref();
        let len = borrow.len();
        let mut this: Vec<MaybeUninit<u8>> = Box::new_uninit_slice(len).into_vec();
        let this_ptr = this[0].as_mut_ptr();
        // SAFETY: The value is not moved nor dropped after this read
        unsafe { ptr::copy_nonoverlapping(&raw const borrow.as_bytes()[0], this_ptr, len); }
        DerefOwn::forget_contents(val);
        // SAFETY: `this` has been inhabited with a value which is valid UTF-8
        unsafe { String::from_utf8_unchecked(transmute(this)) }
    }
}