transient/any.rs
1//! Analogue to the [`std::any`] module, containing re-implementations of
2//! [`Any`] and [`TypeId`] that support non-`'static` types alongside
3//! re-exports of [`type_name`] and [`type_name_of_val`].
4use crate::{
5 transience::{CanRecoverFrom, CanTranscendTo, Transience},
6 transient::Transient,
7};
8use std::marker::{Send, Sync};
9
10/// Re-export from the [`std::any`] module.
11#[rustversion::before(1.76)]
12pub use std::any::type_name;
13
14/// Re-export from the [`std::any`] module.
15#[rustversion::since(1.76)]
16pub use std::any::{type_name, type_name_of_val};
17
18///////////////////////////////////////////////////////////////////////////////
19// `Any` trait
20///////////////////////////////////////////////////////////////////////////////
21
22/// A trait to emulate dynamic typing, modeled after the [`std::any::Any`] trait with
23/// added support for non-`'static` types.
24///
25/// This trait is primarily used as the `dyn Any<R>` trait object, which has its
26/// methods defined on the [`Downcast`] extension trait.
27///
28/// # Differences from `std::any::Any`
29/// - Types must first implement (or derive) the [`Transient`] trait before the
30/// blanket impl for all `T: Transient` will apply to them.
31/// - In addition to importing the `Any` trait, the [`Downcast`] trait must also
32/// be brought into scope for the `dyn Any` methods to become available.
33/// - Non-`'static` types can be erased by parameterizing the trait with the
34/// desired [`Transience`], which the compiler will ensure is compatible. Types
35/// that *are* `'static` can use any `Transience` they want, or exclude the
36/// parameter to use the default of `()`.
37/// - Not all `dyn Any<_>`'s are equal; the type parameter is considered to be
38/// be a part of the type, so `dyn Any<Co<'_>>` is a different type than
39/// `dyn Any<()>` and they could not be stored together in the same `Vec`. To
40/// circumvent this limitation, a type `T` can be erased to any transience that
41/// is a *supertype* of `T::Transience`; for example, a `usize` can be erased
42/// to `dyn Any<Co<'_>>` instead of the default `dyn Any<()>` so that it can
43/// be stored in a `Vec` with covariant types such as `&'a usize`. Note that if
44/// the transience is upcast to a shorter lifetime (or a longer lifetime in the
45/// *contravariant* case), then it can only be safely [`downcast`] to the
46/// shortened lifetime instead of the original (but if you are brave and/or
47/// careful, you can get around this using `unsafe` hacks like raw pointer
48/// casts and [`std::mem::transmute`]).
49/// - The [`Any::type_id`] method is difficult to use on concrete types as
50/// explained in its docstring; using [`TypeId::of_val`] instead.
51/// - The `*_unchecked` methods do not require nightly builds.
52/// - Only `Box`s using the `Global` allocator are supported.
53/// - Only `Sized` types are supported.
54///
55/// This trait has a blanket `impl` for all [`Transient`] types with a compatible
56/// [`Transience`], and cannot be implemented directly.
57///
58/// [`downcast`]: Downcast::downcast
59pub trait Any<R: Transience = ()> {
60 /// Gets the `TypeId` of `self`, typically as an erased `dyn Any` trait object.
61 ///
62 /// Note that this method is much harder to use on a concrete type than the
63 /// `std::any::Any::type_id` method, since the trait's generic parameter and
64 /// blanket implementation means that any concrete type `T` actually has an
65 /// entire family of `Any` implementations (one for each `Transience` type
66 /// it can use to fill the `R` parameter), and the specific implementation
67 /// to use would need to be specified explicitly using the fully qualified
68 /// path (e.g. `<T as Any<Co<'static>>>::type_id(&value)`) even though they
69 /// would all give the same result. To avoid this issue, you can instead use
70 /// the [`TypeId::of_val`] function (e.g. `TypeId::of_val(&value)`) or the
71 /// `Transient::static_type_id` method (e.g. `value.static_type_id()`)
72 fn type_id(&self) -> TypeId;
73}
74
75impl<T: Transient, R: Transience> Any<R> for T
76where
77 T::Transience: CanTranscendTo<R>,
78{
79 #[inline]
80 fn type_id(&self) -> TypeId {
81 TypeId::of::<T>()
82 }
83}
84
85///////////////////////////////////////////////////////////////////////////////
86// `dyn Any` extension traits
87///////////////////////////////////////////////////////////////////////////////
88
89/// Extension trait defining methods for downcasting the [`dyn Any<_>`][Any] trait
90/// object back into a concrete type.
91///
92/// This trait has an implementation provided for the `dyn Any` trait object,
93/// as in not intended to be implemented by downstream types.
94pub trait Downcast<R: Transience> {
95 /// Returns `true` if the concrete type of the erased object is `T`, which can
96 /// be used to predict the outcome of calling the [`downcast`][Self::downcast]
97 /// and similar methods.
98 ///
99 /// Slight caveat: this method is _not actually_ comparing the erased type
100 /// (call it `E`) to the given type `T`; in reality, it is comparing
101 /// `E::Static` to `T::Static` as defined in their [`Transient`] impls. This
102 /// is effectively equivalent for most purposes, but see the [`TypeId::of`]
103 /// documentation for a discussion of the subtle differences (especially
104 /// when using this check in the implementation of `unsafe` code).
105 fn is<T: Transient>(&self) -> bool;
106
107 /// Attempt to downcast the box to a concrete type with its lifetime
108 /// parameters restored, returning the original in the `Err` variant
109 /// if the type was incorrect.
110 fn downcast<T: Transient>(self: Box<Self>) -> Result<Box<T>, Box<Self>>
111 where
112 T::Transience: CanRecoverFrom<R>;
113
114 /// Returns a reference to the inner value with its lifetime parameters
115 /// restored if it is of type `T`, or `None` if it isn't.
116 fn downcast_ref<T: Transient>(&self) -> Option<&T>
117 where
118 T::Transience: CanRecoverFrom<R>;
119
120 /// Returns a mutable reference to the inner value with its lifetime
121 /// parameters restored if it is of type `T`, or `None` if it isn't.
122 fn downcast_mut<T: Transient>(&mut self) -> Option<&mut T>
123 where
124 T::Transience: CanRecoverFrom<R>;
125
126 /// Downcasts the box to a concrete type without compile-time checks.
127 ///
128 /// For a safe alternative see [`downcast`][Downcast::downcast].
129 ///
130 /// # Safety
131 /// The contained value must be of type `T::Static`; calling this method with
132 /// the incorrect type is *undefined behavior*. However, the the caller is _not_
133 /// expected to uphold any lifetime guarantees, since the trait bounds handle
134 /// this statically.
135 unsafe fn downcast_unchecked<T: Transient>(self: Box<Self>) -> Box<T>
136 where
137 T::Transience: CanRecoverFrom<R>;
138
139 /// Downcasts the shared reference to a concrete type without runtime checks.
140 ///
141 /// For a safe alternative see [`downcast_ref`][Downcast::downcast_ref].
142 ///
143 /// # Safety
144 /// The contained value must be of type `T::Static`; calling this method with
145 /// the incorrect type is *undefined behavior*. However, the the caller is _not_
146 /// expected to uphold any lifetime guarantees, since the trait bounds handle
147 /// this statically.
148 unsafe fn downcast_ref_unchecked<T: Transient>(&self) -> &T
149 where
150 T::Transience: CanRecoverFrom<R>;
151
152 /// Downcasts the mutable reference to a concrete type without runtime checks.
153 ///
154 /// For a safe alternative see [`downcast_mut`][Downcast::downcast_mut].
155 ///
156 /// # Safety
157 /// The contained value must be of type `T::Static`; calling this method with
158 /// the incorrect type is *undefined behavior*. However, the the caller is _not_
159 /// expected to uphold any lifetime guarantees, since the trait bounds handle
160 /// this statically.
161 unsafe fn downcast_mut_unchecked<T: Transient>(&mut self) -> &mut T
162 where
163 T::Transience: CanRecoverFrom<R>;
164}
165
166macro_rules! dyn_any_impls {
167 ($($for:tt)*) => {
168 impl<R: Transience> Downcast<R> for dyn Any<R> $($for)* + '_ {
169 #[inline]
170 fn is<T: Transient>(&self) -> bool {
171 self.type_id() == TypeId::of::<T>()
172 }
173
174 #[inline]
175 fn downcast<T: Transient>(self: Box<Self>) -> Result<Box<T>, Box<Self>>
176 where
177 T::Transience: CanRecoverFrom<R>,
178 {
179 if <Self as Downcast<R>>::is::<T>(self.as_ref()) {
180 // We just confirmed that the type is correct.
181 Ok(unsafe { self.downcast_unchecked() })
182 } else {
183 Err(self)
184 }
185 }
186
187 #[inline]
188 fn downcast_ref<T: Transient>(&self) -> Option<&T>
189 where
190 T::Transience: CanRecoverFrom<R>,
191 {
192 if <Self as Downcast<R>>::is::<T>(self) {
193 // We just confirmed that the type is correct.
194 Some(unsafe { self.downcast_ref_unchecked() })
195 } else {
196 None
197 }
198 }
199
200 #[inline]
201 fn downcast_mut<T: Transient>(&mut self) -> Option<&mut T>
202 where
203 T::Transience: CanRecoverFrom<R>,
204 {
205 if <Self as Downcast<R>>::is::<T>(self) {
206 // We just confirmed that the type is correct.
207 Some(unsafe { self.downcast_mut_unchecked() })
208 } else {
209 None
210 }
211 }
212
213 #[inline]
214 unsafe fn downcast_unchecked<T: Transient>(self: Box<Self>) -> Box<T>
215 where
216 T::Transience: CanRecoverFrom<R>,
217 {
218 // The caller is expected to ensure that the inner type is `T::Static`,
219 // which the `Transient` trait guarantees has the same layout as `T`,
220 // so the pointer cast is safe. The trait bound on `T::Transience`
221 // ensures that the lifetime parameters of the returned type satisfy
222 // the necessary subtyping relationships.
223 Box::from_raw(Box::into_raw(self).cast())
224 }
225
226 #[inline]
227 unsafe fn downcast_ref_unchecked<T: Transient>(&self) -> &T
228 where
229 T::Transience: CanRecoverFrom<R>,
230 {
231 // The caller is expected to ensure that the inner type is `T::Static`,
232 // which the `Transient` trait guarantees has the same layout as `T`,
233 // so the pointer casts are safe. The trait bound on `T::Transience`
234 // ensures that the lifetime parameters of the returned type satisfy
235 // the necessary subtyping relationships.
236 &*(self as *const Self).cast()
237 }
238
239 #[inline]
240 unsafe fn downcast_mut_unchecked<T: Transient>(&mut self) -> &mut T
241 where
242 T::Transience: CanRecoverFrom<R>,
243 {
244 // The caller is expected to ensure that the inner type is `T::Static`,
245 // which the `Transient` trait guarantees has the same layout as `T`,
246 // so the pointer casts are safe. The trait bound on `T::Transience`
247 // ensures that the lifetime parameters of the returned type satisfy
248 // the necessary subtyping relationships.
249 &mut *(self as *mut Self).cast()
250 }
251 }
252
253 impl<R: Transience> std::fmt::Debug for dyn Any<R> $($for)* + '_ {
254 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
255 f.write_str("dyn Any<")?;
256 f.write_str(type_name::<R>().rsplit("::").next().unwrap())?;
257 let xtraits = stringify!($($for)*);
258 if xtraits.len() > 0 {
259 f.write_str("> ")?;
260 f.write_str(xtraits)
261 } else {
262 f.write_str(">")
263 }
264 }
265 }
266 };
267}
268
269dyn_any_impls!();
270dyn_any_impls!(+ Send);
271dyn_any_impls!(+ Send + Sync);
272
273///////////////////////////////////////////////////////////////////////////////
274// `TypeID` and its methods
275///////////////////////////////////////////////////////////////////////////////
276
277/// Thin wrapper for [`std::any::TypeId`], which represents a globally unique
278/// identifier for a type.
279///
280/// Each `TypeId` is an opaque object which does not allow inspection of what's
281/// inside but does allow basic operations such as cloning, comparison,
282/// printing, and showing.
283///
284/// While the `std::any::TypeId` type is currently only available for `'static`
285/// types, this wrapped version is instead provided for any type implementing
286/// the [`Transient`] trait defined in this crate by simply querying the `TypeId`
287/// of the `Static` associated type defined in its `Transient` impl.
288///
289/// A slight caveat of this implementation is that this `TypeId` for some type
290/// `T: Transient` is _technically_ the unique identifier for [`T::Static`] as
291/// defined in its `Transient` impl instead of `T` itself, but as long as the
292/// `Transient` trait was implemented correctly (which the `unsafe` implementor
293/// pinky-promised they did), then this "static identity" is effectively equivalent.
294/// However, this identifier ignores all lifetime information about the type,
295/// `&'short str` will have the same `TypeId` as `&'static str`, and `unsafe`
296/// code **should not** assume that it can ignore lifetimes based on the `TypeId`
297/// alone.
298///
299/// Quoting from the `std::any::TypeId` documentation: while `TypeId` implements
300/// `Hash`, `PartialOrd`, and `Ord`, it is worth noting that the hashes and ordering
301/// will vary between Rust releases. Beware of relying on them inside of your code!
302///
303/// # Examples
304/// ```
305/// use transient::{TypeId, Any, Transient};
306///
307/// let static_str = "cookie_monster";
308/// // 'static types have a `TypeId` just like in the `std::any` module (as long
309/// // as they implement the `Transient` trait, which &'static str does); however,
310/// // we use the `Transient::static_type_id` method or `TypeId::of_val` function
311/// // instead of `Any::type_id` when dealing with concrete types to avoid needing
312/// // to use the fully qualified path (see `Any::type_id` docs).
313/// assert_eq!(static_str.static_type_id(), TypeId::of::<&'static str>());
314/// assert_eq!(TypeId::of_val(&static_str), TypeId::of::<&'static str>());
315/// {
316/// let temp_string = static_str.to_string();
317/// let temp_str: &str = &temp_string;
318/// // unlike `std::any`, non-'static types also have a `TypeId`
319/// assert_eq!(temp_str.static_type_id(), TypeId::of::<&'_ str>());
320/// // note that this `TypeId` will match regardless of the lifetime
321/// assert_eq!(temp_str.static_type_id(), TypeId::of::<&'static str>());
322/// }
323/// // this `TypeId` can also be compared to a `std::any::TypeId`
324/// assert_eq!(TypeId::of::<&'_ str>(), std::any::TypeId::of::<&'static str>());
325/// ```
326/// [`T::Static`]: Transient::Static
327#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
328pub struct TypeId(std::any::TypeId);
329
330impl TypeId {
331 /// Returns the `TypeId` of the [`Transient`] type this generic function
332 /// has been instantiated with.
333 ///
334 /// See the [`TypeId`] documentation for a discussion of the subtle differences
335 /// between this identifier and the `std::any::TypeId`.
336 ///
337 /// # Examples
338 ///
339 /// ```
340 /// use transient::{Transient, Any, TypeId};
341 ///
342 /// fn is_string_slice<T: Transient>(_s: &T) -> bool {
343 /// TypeId::of::<&str>() == TypeId::of::<T>()
344 /// }
345 ///
346 /// let string = "cookie monster".to_string();
347 /// let string_slice: &str = &string;
348 ///
349 /// assert_eq!(is_string_slice(&0), false);
350 /// assert_eq!(is_string_slice(&string), false);
351 /// assert_eq!(is_string_slice(&string_slice), true);
352 /// assert_eq!(is_string_slice(&"cookie monster"), true);
353 /// ```
354 #[inline]
355 pub fn of<T: Transient>() -> Self {
356 let () = T::CHECK;
357 TypeId(std::any::TypeId::of::<T::Static>())
358 }
359
360 /// Returns the `TypeId` for the type of the given value.
361 ///
362 /// This is effectively the same as [`TypeId::of`], but allows a value to
363 /// provided so that type inference can be used to get the type `T` instead
364 /// of needing to explicitly specify it.
365 ///
366 /// See the [`TypeId`] documentation for a discussion of the subtle differences
367 /// between this identifier and the [`std::any::TypeId`].
368 #[inline]
369 pub fn of_val<T: Transient>(_value: &T) -> Self {
370 TypeId::of::<T>()
371 }
372}
373
374impl From<std::any::TypeId> for TypeId {
375 #[inline]
376 fn from(value: std::any::TypeId) -> Self {
377 TypeId(value)
378 }
379}
380
381impl From<TypeId> for std::any::TypeId {
382 #[inline]
383 fn from(value: TypeId) -> Self {
384 value.0
385 }
386}
387
388impl PartialEq<std::any::TypeId> for TypeId {
389 #[inline]
390 fn eq(&self, other: &std::any::TypeId) -> bool {
391 self.0.eq(other)
392 }
393}
394
395impl std::fmt::Debug for TypeId {
396 #[inline]
397 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
398 self.0.fmt(f)
399 }
400}
401
402impl std::hash::Hash for TypeId {
403 #[inline]
404 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
405 self.0.hash(state)
406 }
407}
408
409#[cfg(test)]
410// FIXME: move to crate::tests
411mod tests {
412 use super::{Any, Downcast};
413 use crate::{tr::Transient, Co, Inv};
414
415 #[test]
416 fn test_primative() {
417 let val = 5;
418 let valref = &val;
419 let valrefref = &valref;
420
421 let erased: Vec<&dyn Any<Co>> = vec![&5, &valref, &valrefref];
422 assert_eq!(erased[0].downcast_ref::<i32>().unwrap(), &5);
423 assert_eq!(erased[1].downcast_ref::<&i32>().unwrap(), &valref);
424 assert_eq!(erased[2].downcast_ref::<&&i32>().unwrap(), &valrefref);
425
426 // owned `usize`
427 let value = 5_usize;
428 let ts: Box<dyn Any<()>> = Box::new(5_usize);
429 let co: Box<dyn Any<Co>> = Box::new(5_usize);
430 let inv: Box<dyn Any<Inv>> = Box::new(5_usize);
431 assert_eq!(*ts.downcast::<usize>().unwrap(), value);
432 assert_eq!(*co.downcast::<usize>().unwrap(), value);
433 assert_eq!(*inv.downcast::<usize>().unwrap(), value);
434
435 // borrowed `usize`
436 let ts: &dyn Any = &value;
437 let co: &dyn Any<Co> = &value;
438 let inv: &dyn Any<Inv> = &value;
439 assert_eq!(ts.downcast_ref::<usize>().unwrap(), &value);
440 assert_eq!(co.downcast_ref::<usize>().unwrap(), &value);
441 assert_eq!(inv.downcast_ref::<usize>().unwrap(), &value);
442
443 // owned `&usize`
444 let valref: &usize = &value;
445 let co: Box<dyn Any<Co>> = Box::new(valref);
446 let inv: Box<dyn Any<Inv>> = Box::new(valref);
447 assert_eq!(*co.downcast::<&usize>().unwrap(), valref);
448 assert_eq!(*inv.downcast::<&usize>().unwrap(), valref);
449
450 // borrowed `&usize`
451 let co: &dyn Any<Co> = &valref;
452 let inv: &dyn Any<Inv> = &valref;
453 assert_eq!(co.downcast_ref::<&usize>().unwrap(), &valref);
454 assert_eq!(inv.downcast_ref::<&usize>().unwrap(), &valref);
455
456 // owned `&&usize`
457 let valrefref = &valref;
458 let inv_inv: Box<dyn Any<(Inv, Inv)>> = Box::new(valrefref);
459 let inv_co: Box<dyn Any<(Inv, Co)>> = Box::new(valrefref);
460 let co_inv: Box<dyn Any<(Co, Inv)>> = Box::new(valrefref);
461 let co_co: Box<dyn Any<(Co, Co)>> = Box::new(valrefref);
462 let co: Box<dyn Any<Co>> = Box::new(valrefref);
463 let inv: Box<dyn Any<Inv>> = Box::new(valrefref);
464 assert_eq!(*inv_inv.downcast::<&&usize>().unwrap(), valrefref);
465 assert_eq!(*inv_co.downcast::<&&usize>().unwrap(), valrefref);
466 assert_eq!(*co_inv.downcast::<&&usize>().unwrap(), valrefref);
467 assert_eq!(*co_co.downcast::<&&usize>().unwrap(), valrefref);
468 assert_eq!(*co.downcast::<&&usize>().unwrap(), valrefref);
469 assert_eq!(*inv.downcast::<&&usize>().unwrap(), valrefref);
470
471 // borrowed `&&usize`
472 let inv_inv: &dyn Any<(Inv, Inv)> = &valrefref;
473 let co_inv: &dyn Any<(Co, Inv)> = &valrefref;
474 let inv_co: &dyn Any<(Inv, Co)> = &valrefref;
475 let co_co: &dyn Any<(Co, Co)> = &valrefref;
476 let co: &dyn Any<Co> = &valrefref;
477 let inv: &dyn Any<Inv> = &valrefref;
478 assert_eq!(inv_inv.downcast_ref::<&&usize>().unwrap(), &valrefref);
479 assert_eq!(co_inv.downcast_ref::<&&usize>().unwrap(), &valrefref);
480 assert_eq!(inv_co.downcast_ref::<&&usize>().unwrap(), &valrefref);
481 assert_eq!(co_co.downcast_ref::<&&usize>().unwrap(), &valrefref);
482 assert_eq!(co.downcast_ref::<&&usize>().unwrap(), &valrefref);
483 assert_eq!(inv.downcast_ref::<&&usize>().unwrap(), &valrefref);
484
485 {
486 // owned `&mut &mut usize`
487 let mut value = 5_usize;
488 let mut valmut = &mut value;
489 let inv_inv: Box<dyn Any<(Inv, Inv)>> = Box::new(&mut valmut);
490 assert_eq!(
491 *inv_inv.downcast::<&mut &mut usize>().unwrap(),
492 &mut &mut 5usize
493 );
494 let co_inv: Box<dyn Any<(Co, Inv)>> = Box::new(&mut valmut);
495 assert_eq!(
496 *co_inv.downcast::<&mut &mut usize>().unwrap(),
497 &mut &mut 5usize
498 );
499 let inv: Box<dyn Any<Inv>> = Box::new(&mut valmut);
500 assert_eq!(
501 *inv.downcast::<&mut &mut usize>().unwrap(),
502 &mut &mut 5usize
503 );
504 }
505 {
506 // borrowed `&mut &mut usize`
507 let mut value = 5_usize;
508 let mut valmut = &mut value;
509 let valmutmut = &mut valmut;
510 let inv_inv: &dyn Any<(Inv, Inv)> = &valmutmut;
511 assert_eq!(
512 inv_inv.downcast_ref::<&mut &mut usize>().unwrap(),
513 &&mut &mut 5usize
514 );
515 let co_inv: &dyn Any<(Co, Inv)> = &valmutmut;
516 assert_eq!(
517 co_inv.downcast_ref::<&mut &mut usize>().unwrap(),
518 &&mut &mut 5usize
519 );
520 let inv: &dyn Any<Inv> = &valmutmut;
521 assert_eq!(
522 inv.downcast_ref::<&mut &mut usize>().unwrap(),
523 &&mut &mut 5usize
524 );
525 }
526 }
527
528 #[test]
529 fn test_custom() {
530 #[derive(Debug, Clone)]
531 pub struct Usize(usize);
532
533 unsafe impl Transient for Usize {
534 type Static = Usize;
535 type Transience = ();
536 }
537
538 #[derive(Debug, Clone, Copy)]
539 pub struct UsizeRef<'a>(&'a usize);
540
541 unsafe impl<'a> Transient for UsizeRef<'a> {
542 type Static = UsizeRef<'static>;
543 type Transience = Co<'a>;
544 }
545
546 // owned `Usize`
547 let usize_ = Usize(5_usize);
548 let stc: Box<dyn Any<()>> = Box::new(usize_.clone());
549 let inv: Box<dyn Any<Inv>> = Box::new(usize_.clone());
550 let co: Box<dyn Any<Co>> = Box::new(usize_.clone());
551 assert_eq!(stc.downcast::<Usize>().unwrap().0, 5_usize);
552 assert_eq!(inv.downcast::<Usize>().unwrap().0, 5_usize);
553 assert_eq!(co.downcast::<Usize>().unwrap().0, 5_usize);
554
555 // borrowed `Usize`
556 let stc: &dyn Any<()> = &usize_;
557 let inv: &dyn Any<Inv> = &usize_;
558 let co: &dyn Any<Co> = &usize_;
559 assert_eq!(stc.downcast_ref::<Usize>().unwrap().0, 5_usize);
560 assert_eq!(inv.downcast_ref::<Usize>().unwrap().0, 5_usize);
561 assert_eq!(co.downcast_ref::<Usize>().unwrap().0, 5_usize);
562 assert_eq!(&format!("{:?}", stc), "dyn Any<()>");
563
564 // owned `UsizeRef`
565 let usize_ref = UsizeRef(&usize_.0);
566 let inv: Box<dyn Any<Inv>> = Box::new(usize_ref.clone());
567 let co: Box<dyn Any<Co>> = Box::new(usize_ref.clone());
568 assert_eq!(inv.downcast::<UsizeRef>().unwrap().0, &5_usize);
569 assert_eq!(co.downcast::<UsizeRef>().unwrap().0, &5_usize);
570
571 // borrowed `UsizeRef`
572 let inv: &dyn Any<Inv> = &usize_ref;
573 let co: &dyn Any<Co> = &usize_ref;
574 assert_eq!(inv.downcast_ref::<UsizeRef>().unwrap().0, &5_usize);
575 assert_eq!(co.downcast_ref::<UsizeRef>().unwrap().0, &5_usize);
576 assert_eq!(&format!("{:?}", co), "dyn Any<Co>");
577
578 // owned `UsizeRef` + Send
579 let usize_ref = UsizeRef(&usize_.0);
580 let inv: Box<dyn Any<Inv> + Send> = Box::new(usize_ref.clone());
581 let co: Box<dyn Any<Co> + Send> = Box::new(usize_ref.clone());
582 assert_eq!(inv.downcast::<UsizeRef>().unwrap().0, &5_usize);
583 assert_eq!(co.downcast::<UsizeRef>().unwrap().0, &5_usize);
584
585 // borrowed `UsizeRef` + Send
586 let inv: &(dyn Any<Inv> + Send) = &usize_ref;
587 let co: &(dyn Any<Co> + Send) = &usize_ref;
588 assert_eq!(inv.downcast_ref::<UsizeRef>().unwrap().0, &5_usize);
589 assert_eq!(co.downcast_ref::<UsizeRef>().unwrap().0, &5_usize);
590 assert_eq!(&format!("{:?}", co), "dyn Any<Co> + Send");
591
592 // owned `UsizeRef` + Send + Sync
593 let usize_ref = UsizeRef(&usize_.0);
594 let inv: Box<dyn Any<Inv> + Send + Sync> = Box::new(usize_ref.clone());
595 let co: Box<dyn Any<Co> + Send + Sync> = Box::new(usize_ref.clone());
596 assert_eq!(inv.downcast::<UsizeRef>().unwrap().0, &5_usize);
597 assert_eq!(co.downcast::<UsizeRef>().unwrap().0, &5_usize);
598
599 // borrowed `UsizeRef` + Send + Sync
600 let inv: &(dyn Any<Inv> + Send + Sync) = &usize_ref;
601 let co: &(dyn Any<Co> + Send + Sync) = &usize_ref;
602 assert_eq!(inv.downcast_ref::<UsizeRef>().unwrap().0, &5_usize);
603 assert_eq!(co.downcast_ref::<UsizeRef>().unwrap().0, &5_usize);
604 assert_eq!(&format!("{:?}", inv), "dyn Any<Inv> + Send + Sync")
605 }
606}