#[cfg(feature = "unstable_out")]
pub mod out {
use crate::Own;
use core::mem::{MaybeUninit, transmute_prefix};
use core::ptr::NonNull;
#[repr(transparent)]
pub struct Out<'a, T> {
inner: &'a mut MaybeUninit<T>
}
const impl<'a, T> Out<'a, T> {
fn write(self, val: Own<T>) -> &'a mut T {
let src: NonNull<T> = unsafe { transmute_prefix(val) };
let dst = unsafe { NonNull::new_unchecked(self.inner.as_mut_ptr()) };
unsafe { src.copy_to_nonoverlapping(dst, 1); }
unsafe { transmute_prefix(self) }
}
unsafe fn assume_initialized(self) -> &'a mut T {
unsafe { transmute_prefix(self) }
}
}
impl<'a, T> Drop for Out<'a, T> {
#[rustc_nounwind]
fn drop(&mut self) {
panic!("Out reference was dropped without initialization!")
}
}
#[macro_export]
macro_rules! let_out {
(let out $p:pat_param) => {{
super let __OUT_UNINIT = ::core::mem::MaybeUninit::uninit();
&mut __OUT_UNINIT
}};
}
pub trait Relocate {
fn relocate(self: Own<Self>, dst: Out<Self>)
where
Self: Sized;
}
impl<T> Relocate for T {
#[inline(always)]
default fn relocate(self: Own<Self>, dst: Out<Self>) {
dst.write(self);
}
}
}
#[cfg(feature = "unstable_dyn_example")]
pub mod dyn_example {
use crate::Own;
use crate::traits::DerefMove;
use core::marker::PhantomData;
use core::mem::transmute_prefix;
use core::ptr::NonNull;
pub struct Output(usize);
pub trait X {
fn do_stuff(self) -> Output;
}
struct DynXMeta {
size: usize,
do_stuff: unsafe fn(NonNull<()>) -> Output,
}
const fn dyn_x_meta<'a, T: X + 'a>() -> &'a DynXMeta {
&const {
DynXMeta {
size: size_of::<T>(),
do_stuff: unsafe {
transmute_prefix(do_stuff_through_own_ref::<T> as fn(Own<'a, T>) -> Output)
}
}
}
}
fn do_stuff_through_own_ref<T: X>(this: Own<T>) -> Output {
this.deref_move().do_stuff()
}
pub struct OwnDynXPointee<'a> {
meta: &'a DynXMeta,
ptr: NonNull<()>,
phantom: PhantomData<Own<'a, ()>>
}
impl<'a> X for OwnDynXPointee<'a> {
fn do_stuff(self) -> Output {
unsafe { (self.meta.do_stuff)(self.ptr) }
}
}
impl<'a> OwnDynXPointee<'a> {
pub const fn of<T: X>(ptr: Own<'a, T>) -> Self {
Self {
meta: const { dyn_x_meta::<T>() },
ptr: unsafe { transmute_prefix(ptr) },
phantom: PhantomData
}
}
}
}
#[cfg(feature = "unstable_project")]
pub mod project {
use crate::Own;
use core::field::Field;
use core::marker::PhantomData;
use core::mem::{ManuallyDrop, MaybeDangling};
use core::ptr::NonNull;
pub struct CellRef<'a, T: ?Sized> {
ptr: NonNull<T>,
phantom: PhantomData<(*mut T, fn(&'a ()) -> &'a ())>,
}
impl<'a, T> CellRef<'a, T> {}
pub unsafe fn project<F: Field>(from: *mut ManuallyDrop<F::Base>, _: MaybeDangling<&mut F::Type>) -> Own<'_, F::Type> {
let ptr = from as *mut u8;
unsafe {
Own::new(&mut *(ptr.wrapping_add(F::OFFSET) as *mut ManuallyDrop<F::Type>))
}
}
#[cfg(test)]
mod test {
use crate::macros::own;
use crate::traits::DerefMove;
use crate::unstable::project::project;
use alloc::boxed::Box;
use core::field::field_of;
use core::mem::MaybeDangling;
struct E {
x: usize,
y: Box<bool>,
}
#[test]
fn test_projection() {
let val = own!(E { x: 10, y: Box::new(false) });
let inner = val.into_inner();
let ptr = &raw mut *inner;
let borrow = &mut **inner;
let x = unsafe { project::<field_of!(E, x)>(ptr, MaybeDangling::new(&mut borrow.x)) };
let y = unsafe { project::<field_of!(E, y)>(ptr, MaybeDangling::new(&mut borrow.y)) };
assert!(x.deref_move() == 10);
assert!(*y.deref_move() == false);
}
}
}
#[cfg(feature = "unstable_box_alias")]
pub mod box_alias {
use alloc::boxed::Box;
use core::alloc::{AllocError, Allocator, Layout};
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ptr::NonNull;
pub type Own<'a, T: ?Sized> = Box<T, PhantomSlot<'a>>;
pub struct PhantomSlot<'a>(PhantomData<&'a mut ()>);
impl<'a> PhantomSlot<'a> {
pub unsafe fn own<T: ?Sized>(val: &'a mut ManuallyDrop<T>) -> crate::Own<'a, T> {
unsafe {
Box::from_raw_in(&raw mut**val, Self(PhantomData))
}
}
}
unsafe impl<'a> Allocator for PhantomSlot<'a> {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
Err(AllocError)
}
unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout) {}
}
}