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}