Skip to main content

midenc_hir/
any.rs

1use alloc::{boxed::Box, rc::Rc};
2use core::{any::Any, marker::Unsize};
3
4pub trait AsAny: Any + 'static {
5    fn type_name(&self) -> &'static str;
6    fn as_any(&self) -> &dyn Any;
7    fn as_any_mut(&mut self) -> &mut dyn Any;
8    fn into_any(self: Box<Self>) -> Box<dyn Any>;
9    fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any>;
10}
11
12impl<T: Any + 'static> AsAny for T {
13    #[inline(always)]
14    default fn type_name(&self) -> &'static str {
15        core::any::type_name::<T>()
16    }
17
18    #[inline(always)]
19    default fn as_any(&self) -> &dyn Any {
20        self
21    }
22
23    #[inline(always)]
24    default fn as_any_mut(&mut self) -> &mut dyn Any {
25        self
26    }
27
28    #[inline(always)]
29    default fn into_any(self: Box<Self>) -> Box<dyn Any> {
30        self
31    }
32
33    #[inline(always)]
34    default fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any> {
35        self
36    }
37}
38
39/// # Safety
40///
41/// This trait is not safe (or possible) to implement manually.
42///
43/// It is automatically derived for all `T: Unsize<Trait>`
44pub unsafe trait Is<Trait: ?Sized>: Unsize<Trait> {}
45unsafe impl<Trait: ?Sized, T> Is<Trait> for T where T: ?Sized + Unsize<Trait> {}
46
47pub trait IsObjOf<T: ?Sized> {}
48impl<T, Trait> IsObjOf<T> for Trait
49where
50    T: ?Sized + Is<Trait>,
51    Trait: ?Sized,
52{
53}
54
55#[allow(unused)]
56pub trait DowncastRef<To: ?Sized>: IsObjOf<To> {
57    fn downcast_ref(&self) -> Option<&To>;
58    fn downcast_mut(&mut self) -> Option<&mut To>;
59}
60impl<From, To> DowncastRef<To> for From
61where
62    From: ?Sized,
63    To: ?Sized + DowncastFromRef<From>,
64{
65    #[inline(always)]
66    fn downcast_ref(&self) -> Option<&To> {
67        To::downcast_from_ref(self)
68    }
69
70    #[inline(always)]
71    fn downcast_mut(&mut self) -> Option<&mut To> {
72        To::downcast_from_mut(self)
73    }
74}
75
76pub trait DowncastFromRef<From: ?Sized>: Is<From> {
77    fn downcast_from_ref(from: &From) -> Option<&Self>;
78    fn downcast_from_mut(from: &mut From) -> Option<&mut Self>;
79}
80impl<From, To> DowncastFromRef<From> for To
81where
82    From: ?Sized + AsAny,
83    To: Is<From> + 'static,
84{
85    #[inline]
86    fn downcast_from_ref(from: &From) -> Option<&Self> {
87        from.as_any().downcast_ref()
88    }
89
90    #[inline]
91    fn downcast_from_mut(from: &mut From) -> Option<&mut Self> {
92        from.as_any_mut().downcast_mut()
93    }
94}
95
96#[allow(unused)]
97pub trait Downcast<To: ?Sized, Obj: ?Sized>: DowncastRef<To> + Is<Obj> {
98    fn downcast(self: Box<Self>) -> Result<Box<To>, Box<Obj>>;
99}
100impl<From, To, Obj> Downcast<To, Obj> for From
101where
102    From: ?Sized + DowncastRef<To> + Is<Obj>,
103    To: ?Sized + DowncastFrom<Self, Obj>,
104    Obj: ?Sized,
105{
106    #[inline]
107    fn downcast(self: Box<Self>) -> Result<Box<To>, Box<Obj>> {
108        To::downcast_from(self)
109    }
110}
111
112pub trait DowncastFrom<From, Obj>: DowncastFromRef<From>
113where
114    From: ?Sized + Is<Obj>,
115    Obj: ?Sized,
116{
117    #[allow(dead_code)]
118    fn downcast_from(from: Box<From>) -> Result<Box<Self>, Box<Obj>>;
119}
120impl<From, To, Obj> DowncastFrom<From, Obj> for To
121where
122    From: ?Sized + Is<Obj> + AsAny + 'static,
123    To: DowncastFromRef<From> + 'static,
124    Obj: ?Sized,
125{
126    fn downcast_from(from: Box<From>) -> Result<Box<Self>, Box<Obj>> {
127        if !from.as_any().is::<To>() {
128            Ok(from.into_any().downcast().unwrap())
129        } else {
130            Err(from)
131        }
132    }
133}
134
135pub trait Upcast<To: ?Sized>: TryUpcastRef<To> {
136    #[allow(dead_code)]
137    fn upcast_ref(&self) -> &To;
138    #[allow(dead_code)]
139    fn upcast_mut(&mut self) -> &mut To;
140    #[allow(dead_code)]
141    fn upcast(self: Box<Self>) -> Box<To>;
142}
143impl<From, To> Upcast<To> for From
144where
145    From: ?Sized + Is<To>,
146    To: ?Sized,
147{
148    #[inline(always)]
149    fn upcast_ref(&self) -> &To {
150        self
151    }
152
153    #[inline(always)]
154    fn upcast_mut(&mut self) -> &mut To {
155        self
156    }
157
158    #[inline(always)]
159    fn upcast(self: Box<Self>) -> Box<To> {
160        self
161    }
162}
163
164pub trait TryUpcastRef<To>: Is<To>
165where
166    To: ?Sized,
167{
168    #[allow(unused)]
169    fn is_of(&self) -> bool;
170    #[allow(dead_code)]
171    fn try_upcast_ref(&self) -> Option<&To>;
172    #[allow(dead_code)]
173    fn try_upcast_mut(&mut self) -> Option<&mut To>;
174}
175impl<From, To> TryUpcastRef<To> for From
176where
177    From: Upcast<To> + ?Sized,
178    To: ?Sized,
179{
180    #[inline(always)]
181    fn is_of(&self) -> bool {
182        true
183    }
184
185    #[inline(always)]
186    fn try_upcast_ref(&self) -> Option<&To> {
187        Some(self.upcast_ref())
188    }
189
190    #[inline(always)]
191    fn try_upcast_mut(&mut self) -> Option<&mut To> {
192        Some(self.upcast_mut())
193    }
194}
195
196pub trait TryUpcast<To, Obj>: Is<Obj> + TryUpcastRef<To>
197where
198    To: ?Sized,
199    Obj: ?Sized,
200{
201    #[allow(dead_code)]
202    #[inline(always)]
203    fn try_upcast(self: Box<Self>) -> Result<Box<To>, Box<Obj>> {
204        Err(self)
205    }
206}
207impl<From, To, Obj> TryUpcast<To, Obj> for From
208where
209    From: Is<Obj> + Upcast<To> + ?Sized,
210    To: ?Sized,
211    Obj: ?Sized,
212{
213    #[inline]
214    fn try_upcast(self: Box<Self>) -> Result<Box<To>, Box<Obj>> {
215        Ok(self.upcast())
216    }
217}
218
219/// Upcasts a type into a trait object
220#[allow(unused)]
221pub trait UpcastFrom<From>
222where
223    From: ?Sized,
224{
225    fn upcast_from_ref(from: &From) -> &Self;
226    fn upcast_from_mut(from: &mut From) -> &mut Self;
227    fn upcast_from(from: Box<From>) -> Box<Self>;
228}
229
230impl<From, To> UpcastFrom<From> for To
231where
232    From: Upcast<To> + ?Sized,
233    To: ?Sized,
234{
235    #[inline]
236    fn upcast_from_ref(from: &From) -> &Self {
237        from.upcast_ref()
238    }
239
240    #[inline]
241    fn upcast_from_mut(from: &mut From) -> &mut Self {
242        from.upcast_mut()
243    }
244
245    #[inline]
246    fn upcast_from(from: Box<From>) -> Box<Self> {
247        from.upcast()
248    }
249}
250
251#[allow(unused)]
252pub trait TryUpcastFromRef<From>: IsObjOf<From>
253where
254    From: ?Sized,
255{
256    fn try_upcast_from_ref(from: &From) -> Option<&Self>;
257    fn try_upcast_from_mut(from: &mut From) -> Option<&mut Self>;
258}
259
260impl<From, To> TryUpcastFromRef<From> for To
261where
262    From: TryUpcastRef<To> + ?Sized,
263    To: ?Sized,
264{
265    #[inline]
266    fn try_upcast_from_ref(from: &From) -> Option<&Self> {
267        from.try_upcast_ref()
268    }
269
270    #[inline]
271    fn try_upcast_from_mut(from: &mut From) -> Option<&mut Self> {
272        from.try_upcast_mut()
273    }
274}
275
276#[allow(unused)]
277pub trait TryUpcastFrom<From, Obj>: TryUpcastFromRef<From>
278where
279    From: Is<Obj> + ?Sized,
280    Obj: ?Sized,
281{
282    fn try_upcast_from(from: Box<From>) -> Result<Box<Self>, Box<Obj>>;
283}
284
285impl<From, To, Obj> TryUpcastFrom<From, Obj> for To
286where
287    From: TryUpcast<Self, Obj> + ?Sized,
288    To: ?Sized,
289    Obj: ?Sized,
290{
291    #[inline]
292    fn try_upcast_from(from: Box<From>) -> Result<Box<Self>, Box<Obj>> {
293        from.try_upcast()
294    }
295}