1#![no_std]
2#![cfg_attr(feature = "any-ptr", allow(incomplete_features))]
3#![cfg_attr(feature = "any-ptr", feature(generic_const_exprs, specialization))]
4#![feature(unsize, ptr_metadata, exact_size_is_empty, trivial_bounds)]
5#[cfg(not(feature = "any-ptr"))]
8extern crate alloc;
9
10mod impls;
11
12#[cfg(not(feature = "any-ptr"))]
13use alloc::boxed::Box;
14use core::{
15 marker::Unsize,
16 mem::{self, ManuallyDrop},
17 ops::{Deref, DerefMut},
18 ptr::{self, Pointee},
19};
20
21#[repr(transparent)]
22#[derive(Copy, Clone)]
23pub struct PtrRepr(pub(self) *const ());
24
25pub unsafe fn faith_metadata<Ptr, Dyn: ?Sized>(val: Ptr) -> (PtrRepr, <Dyn as Pointee>::Metadata)
26where
27 Ptr: Unsize<Dyn>,
28{
29 let val = &*ManuallyDrop::new(val);
30 (mem::transmute_copy(val), ptr::metadata(val as *const Dyn))
31}
32
33pub trait PointerLike<Dyn: ?Sized>: Sized {
34 fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata);
35
36 fn do_dyn(self) -> DynPtr<Dyn>
37 where
38 Self: Unsize<Dyn>,
39 {
40 unsafe { DynPtr::from_parts(faith_metadata::<_, Dyn>(self)) }
42 }
43}
44
45struct AlignOf<const N: usize>;
46struct SizeOf<const N: usize>;
47
48trait SamePtr {}
49
50impl SamePtr for SizeOf<{ mem::size_of::<PtrRepr>() }> {}
51impl SamePtr for AlignOf<{ mem::align_of::<PtrRepr>() }> {}
52
53#[cfg(feature = "any-ptr")]
54impl<Ptr, Dyn: ?Sized> PointerLike<Dyn> for Ptr
55where
56 Ptr: Unsize<Dyn>,
57 SizeOf<{ mem::size_of::<Ptr>() }>: SamePtr,
58 AlignOf<{ mem::align_of::<Ptr>() }>: SamePtr,
59{
60 fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata) {
61 unsafe { faith_metadata::<_, Dyn>(self) }
63 }
64}
65
66#[cfg(not(feature = "any-ptr"))]
67impl<T, Dyn: ?Sized> PointerLike<Dyn> for Box<T>
68where
69 Self: Unsize<Dyn>,
70{
71 fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata) {
72 unsafe { faith_metadata::<_, Dyn>(self) }
73 }
74}
75
76#[cfg(not(feature = "any-ptr"))]
77impl<Dyn: ?Sized> PointerLike<Dyn> for *const ()
78where
79 Self: Unsize<Dyn>,
80{
81 fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata) {
82 unsafe { faith_metadata::<_, Dyn>(self) }
83 }
84}
85
86#[cfg(not(feature = "any-ptr"))]
87impl<Dyn: ?Sized> PointerLike<Dyn> for usize
88where
89 Self: Unsize<Dyn>,
90{
91 fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata) {
92 unsafe { faith_metadata::<_, Dyn>(self) }
93 }
94}
95
96#[repr(C)]
97pub struct DynPtr<Dyn: ?Sized> {
98 repr: PtrRepr,
99 meta: <Dyn as Pointee>::Metadata,
100}
101
102unsafe impl<Dyn: ?Sized + Sync> Sync for DynPtr<Dyn> {}
103unsafe impl<Dyn: ?Sized + Send> Send for DynPtr<Dyn> {}
104
105impl<Dyn: ?Sized> DynPtr<Dyn> {
106 pub fn new<T>(val: T) -> Self
107 where
108 T: PointerLike<Dyn>,
109 {
110 unsafe { Self::from_parts(val.meta_repr()) }
112 }
113
114 pub unsafe fn from_parts((repr, meta): (PtrRepr, <Dyn as Pointee>::Metadata)) -> Self {
115 Self { repr, meta }
116 }
117
118 fn const_ptr(&self) -> *const Dyn {
119 ptr::from_raw_parts(ptr::addr_of!(self.repr).cast(), self.meta)
120 }
121
122 fn mut_ptr(&mut self) -> *mut Dyn {
123 ptr::from_raw_parts_mut(ptr::addr_of_mut!(self.repr).cast(), self.meta)
124 }
125}
126
127impl<Dyn: ?Sized> Deref for DynPtr<Dyn> {
128 type Target = Dyn;
129
130 fn deref(&self) -> &Self::Target {
131 unsafe { &*self.const_ptr() }
132 }
133}
134
135impl<Dyn: ?Sized> DerefMut for DynPtr<Dyn> {
136 fn deref_mut(&mut self) -> &mut Self::Target {
137 unsafe { &mut *self.mut_ptr() }
138 }
139}
140
141impl<Dyn: ?Sized> Drop for DynPtr<Dyn> {
142 fn drop(&mut self) {
143 unsafe { ptr::drop_in_place(self.mut_ptr()) }
144 }
145}
146
147pub type Dyn<Trait> = DynPtr<Trait>;