dungeon_cell/vtable/
lifetime_vtable.rs1use core::fmt;
2
3use crate::bound::{Dynamic, Subset};
4use crate::lifetime_type_id::{LifetimeTypeId, StaticForm};
5use crate::marker_traits::IsBound;
6
7use super::{
8 BoundsImpl, ConstVTableOf, Descriptor, Inspect, VTable, VTableOf,
9 VTableSubset,
10};
11
12#[derive(Clone)]
37#[repr(C)]
38pub struct LifetimeVTable<'a, B> {
39 bounds_impl: BoundsImpl<B>,
40 descriptor: Descriptor<Lifetime<'a>>,
41}
42
43impl<'a, B> fmt::Debug for LifetimeVTable<'a, B> {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 f.debug_struct("LifetimeVTable")
46 .field("type_name", &self.descriptor.type_name())
47 .field("size", &self.descriptor.size)
48 .field("alignment", &self.descriptor.alignment)
49 .finish()
50 }
51}
52
53impl<'a, B: IsBound> LifetimeVTable<'a, B> {
54 pub const fn new<T>() -> Self
58 where
59 T: Dynamic<B> + StaticForm<'a>,
60 {
61 <Self as ConstVTableOf<T>>::INSTANCE
62 }
63}
64
65#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
79pub struct Lifetime<'a>(LifetimeTypeId<'a>);
80
81unsafe impl<'a, T: StaticForm<'a>> Inspect<Lifetime<'a>> for T {
84 fn inspect() -> Lifetime<'a> {
85 Lifetime(LifetimeTypeId::of::<T>())
86 }
87}
88
89unsafe impl<'a, B: IsBound> VTable for LifetimeVTable<'a, B> {
93 type Bounds = B;
94
95 type Id = Lifetime<'a>;
96
97 fn descriptor(&self) -> &super::Descriptor<Self::Id> {
98 &self.descriptor
99 }
100
101 fn bound_impl(&self) -> &super::BoundsImpl<Self::Bounds> {
102 &self.bounds_impl
103 }
104}
105
106unsafe impl<'a, B: IsBound, Bnew: IsBound> VTableSubset<Bnew> for LifetimeVTable<'a, B>
108where
109 Bnew: Subset<B>,
110{
111 type Subset = LifetimeVTable<'a, Bnew>;
112
113 fn into_subset(self) -> Self::Subset {
114 LifetimeVTable {
115 bounds_impl: self.bounds_impl.into_subset::<Bnew>(),
116 descriptor: self.descriptor,
117 }
118 }
119}
120
121unsafe impl<'a, 'b, B: IsBound, Bnew: IsBound> VTableSubset<Bnew>
123 for &'a LifetimeVTable<'b, B>
124where
125 Bnew: Subset<B>,
126{
127 type Subset = &'a LifetimeVTable<'b, Bnew>;
128
129 fn into_subset(self) -> Self::Subset {
130 unsafe {
134 &*(self as *const LifetimeVTable<'b, B>
135 as *const LifetimeVTable<'b, Bnew>)
136 }
137 }
138}
139
140unsafe impl<'a, T, B: IsBound> VTableOf<T> for LifetimeVTable<'a, B>
142where
143 T: Dynamic<B> + StaticForm<'a>,
144{
145 fn instance() -> Self {
146 Self::new::<T>()
147 }
148}
149
150unsafe impl<'a, T, B: IsBound> ConstVTableOf<T> for LifetimeVTable<'a, B>
152where
153 T: Dynamic<B> + StaticForm<'a>,
154{
155 const INSTANCE: Self = Self {
156 bounds_impl: BoundsImpl::new::<T>(),
157 descriptor: Descriptor::new::<T>(),
158 };
159}
160
161unsafe impl<'a, 'b, T, B: IsBound> VTableOf<T> for &'b LifetimeVTable<'a, B>
163where
164 T: Dynamic<B> + StaticForm<'a>,
165{
166 fn instance() -> Self {
167 &ConstVTableOf::<T>::INSTANCE
168 }
169}
170
171unsafe impl<'a, 'b, T, B: IsBound> ConstVTableOf<T>
173 for &'b LifetimeVTable<'a, B>
174where
175 T: Dynamic<B> + StaticForm<'a>,
176{
177 const INSTANCE: Self = &ConstVTableOf::<T>::INSTANCE;
178}
179
180#[cfg(test)]
181mod test {
182 use core::sync::atomic::AtomicBool;
183
184 use crate::bound::bounds;
185
186 use super::*;
187
188 #[test]
189 fn has_debug() {
190 let _ = format!("{:?}", LifetimeVTable::<bounds::Normal>::new::<i32>());
191 }
192
193 #[test]
194 fn can_drop_a_t() {
195 static Y: AtomicBool = AtomicBool::new(false);
196
197 struct X {
198 a: i32,
199 }
200
201 impl Drop for X {
202 fn drop(&mut self) {
203 assert_eq!(self.a, 123);
204
205 Y.store(true, core::sync::atomic::Ordering::Relaxed);
206 }
207 }
208
209 }
217
218 #[test]
219 fn vtable_interface() {
220 fn assert_for<T: 'static>() {
221 }
234
235 assert_for::<i32>();
236 assert_for::<String>();
237 assert_for::<()>();
238 assert_for::<u8>();
239 assert_for::<[i32; 100]>();
240 }
241}