• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![deny(unsafe_code)]
2 #![cfg_attr(not(feature = "std"), no_std)]
3 //! [![Build status](https://img.shields.io/github/workflow/status/marcianx/downcast-rs/CI/master)](https://github.com/marcianx/downcast-rs/actions)
4 //! [![Latest version](https://img.shields.io/crates/v/downcast-rs.svg)](https://crates.io/crates/downcast-rs)
5 //! [![Documentation](https://docs.rs/downcast-rs/badge.svg)](https://docs.rs/downcast-rs)
6 //!
7 //! Rust enums are great for types where all variations are known beforehand. But a
8 //! container of user-defined types requires an open-ended type like a **trait
9 //! object**. Some applications may want to cast these trait objects back to the
10 //! original concrete types to access additional functionality and performant
11 //! inlined implementations.
12 //!
13 //! `downcast-rs` adds this downcasting support to trait objects using only safe
14 //! Rust. It supports **type parameters**, **associated types**, and **constraints**.
15 //!
16 //! # Usage
17 //!
18 //! Add the following to your `Cargo.toml`:
19 //!
20 //! ```toml
21 //! [dependencies]
22 //! downcast-rs = "1.2.0"
23 //! ```
24 //!
25 //! This crate is `no_std` compatible. To use it without `std`:
26 //!
27 //! ```toml
28 //! [dependencies]
29 //! downcast-rs = { version = "1.2.0", default-features = false }
30 //! ```
31 //!
32 //! To make a trait downcastable, make it extend either `downcast::Downcast` or
33 //! `downcast::DowncastSync` and invoke `impl_downcast!` on it as in the examples
34 //! below.
35 //!
36 //! Since 1.1.0, the minimum supported Rust version is 1.33 to support `Rc` and `Arc`
37 //! in the receiver position.
38 //!
39 //! ```
40 //! # #[macro_use]
41 //! # extern crate downcast_rs;
42 //! # use downcast_rs::{Downcast, DowncastSync};
43 //! trait Trait: Downcast {}
44 //! impl_downcast!(Trait);
45 //!
46 //! // Also supports downcasting `Arc`-ed trait objects by extending `DowncastSync`
47 //! // and starting `impl_downcast!` with `sync`.
48 //! trait TraitSync: DowncastSync {}
49 //! impl_downcast!(sync TraitSync);
50 //!
51 //! // With type parameters.
52 //! trait TraitGeneric1<T>: Downcast {}
53 //! impl_downcast!(TraitGeneric1<T>);
54 //!
55 //! // With associated types.
56 //! trait TraitGeneric2: Downcast { type G; type H; }
57 //! impl_downcast!(TraitGeneric2 assoc G, H);
58 //!
59 //! // With constraints on types.
60 //! trait TraitGeneric3<T: Copy>: Downcast {
61 //!     type H: Clone;
62 //! }
63 //! impl_downcast!(TraitGeneric3<T> assoc H where T: Copy, H: Clone);
64 //!
65 //! // With concrete types.
66 //! trait TraitConcrete1<T: Copy>: Downcast {}
67 //! impl_downcast!(concrete TraitConcrete1<u32>);
68 //!
69 //! trait TraitConcrete2<T: Copy>: Downcast { type H; }
70 //! impl_downcast!(concrete TraitConcrete2<u32> assoc H=f64);
71 //! # fn main() {}
72 //! ```
73 //!
74 //! # Example without generics
75 //!
76 //! ```
77 //! # use std::rc::Rc;
78 //! # use std::sync::Arc;
79 //! // Import macro via `macro_use` pre-1.30.
80 //! #[macro_use]
81 //! extern crate downcast_rs;
82 //! use downcast_rs::DowncastSync;
83 //!
84 //! // To create a trait with downcasting methods, extend `Downcast` or `DowncastSync`
85 //! // and run `impl_downcast!()` on the trait.
86 //! trait Base: DowncastSync {}
87 //! impl_downcast!(sync Base);  // `sync` => also produce `Arc` downcasts.
88 //!
89 //! // Concrete types implementing Base.
90 //! #[derive(Debug)]
91 //! struct Foo(u32);
92 //! impl Base for Foo {}
93 //! #[derive(Debug)]
94 //! struct Bar(f64);
95 //! impl Base for Bar {}
96 //!
97 //! fn main() {
98 //!     // Create a trait object.
99 //!     let mut base: Box<Base> = Box::new(Foo(42));
100 //!
101 //!     // Try sequential downcasts.
102 //!     if let Some(foo) = base.downcast_ref::<Foo>() {
103 //!         assert_eq!(foo.0, 42);
104 //!     } else if let Some(bar) = base.downcast_ref::<Bar>() {
105 //!         assert_eq!(bar.0, 42.0);
106 //!     }
107 //!
108 //!     assert!(base.is::<Foo>());
109 //!
110 //!     // Fail to convert `Box<Base>` into `Box<Bar>`.
111 //!     let res = base.downcast::<Bar>();
112 //!     assert!(res.is_err());
113 //!     let base = res.unwrap_err();
114 //!     // Convert `Box<Base>` into `Box<Foo>`.
115 //!     assert_eq!(42, base.downcast::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
116 //!
117 //!     // Also works with `Rc`.
118 //!     let mut rc: Rc<Base> = Rc::new(Foo(42));
119 //!     assert_eq!(42, rc.downcast_rc::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
120 //!
121 //!     // Since this trait is `Sync`, it also supports `Arc` downcasts.
122 //!     let mut arc: Arc<Base> = Arc::new(Foo(42));
123 //!     assert_eq!(42, arc.downcast_arc::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
124 //! }
125 //! ```
126 //!
127 //! # Example with a generic trait with associated types and constraints
128 //!
129 //! ```
130 //! // Can call macro via namespace since rust 1.30.
131 //! extern crate downcast_rs;
132 //! use downcast_rs::Downcast;
133 //!
134 //! // To create a trait with downcasting methods, extend `Downcast` or `DowncastSync`
135 //! // and run `impl_downcast!()` on the trait.
136 //! trait Base<T: Clone>: Downcast { type H: Copy; }
137 //! downcast_rs::impl_downcast!(Base<T> assoc H where T: Clone, H: Copy);
138 //! // or: impl_downcast!(concrete Base<u32> assoc H=f32)
139 //!
140 //! // Concrete types implementing Base.
141 //! struct Foo(u32);
142 //! impl Base<u32> for Foo { type H = f32; }
143 //! struct Bar(f64);
144 //! impl Base<u32> for Bar { type H = f32; }
145 //!
146 //! fn main() {
147 //!     // Create a trait object.
148 //!     let mut base: Box<Base<u32, H=f32>> = Box::new(Bar(42.0));
149 //!
150 //!     // Try sequential downcasts.
151 //!     if let Some(foo) = base.downcast_ref::<Foo>() {
152 //!         assert_eq!(foo.0, 42);
153 //!     } else if let Some(bar) = base.downcast_ref::<Bar>() {
154 //!         assert_eq!(bar.0, 42.0);
155 //!     }
156 //!
157 //!     assert!(base.is::<Bar>());
158 //! }
159 //! ```
160 
161 // for compatibility with no std and macros
162 #[doc(hidden)]
163 #[cfg(not(feature = "std"))]
164 pub extern crate core as __std;
165 #[doc(hidden)]
166 #[cfg(feature = "std")]
167 pub extern crate std as __std;
168 #[doc(hidden)]
169 pub extern crate alloc as __alloc;
170 
171 use __std::any::Any;
172 use __alloc::{boxed::Box, rc::Rc, sync::Arc};
173 
174 /// Supports conversion to `Any`. Traits to be extended by `impl_downcast!` must extend `Downcast`.
175 pub trait Downcast: Any {
176     /// Convert `Box<dyn Trait>` (where `Trait: Downcast`) to `Box<dyn Any>`. `Box<dyn Any>` can
177     /// then be further `downcast` into `Box<ConcreteType>` where `ConcreteType` implements `Trait`.
into_any(self: Box<Self>) -> Box<dyn Any>178     fn into_any(self: Box<Self>) -> Box<dyn Any>;
179     /// Convert `Rc<Trait>` (where `Trait: Downcast`) to `Rc<Any>`. `Rc<Any>` can then be
180     /// further `downcast` into `Rc<ConcreteType>` where `ConcreteType` implements `Trait`.
into_any_rc(self: Rc<Self>) -> Rc<dyn Any>181     fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any>;
182     /// Convert `&Trait` (where `Trait: Downcast`) to `&Any`. This is needed since Rust cannot
183     /// generate `&Any`'s vtable from `&Trait`'s.
as_any(&self) -> &dyn Any184     fn as_any(&self) -> &dyn Any;
185     /// Convert `&mut Trait` (where `Trait: Downcast`) to `&Any`. This is needed since Rust cannot
186     /// generate `&mut Any`'s vtable from `&mut Trait`'s.
as_any_mut(&mut self) -> &mut dyn Any187     fn as_any_mut(&mut self) -> &mut dyn Any;
188 }
189 
190 impl<T: Any> Downcast for T {
into_any(self: Box<Self>) -> Box<dyn Any>191     fn into_any(self: Box<Self>) -> Box<dyn Any> { self }
into_any_rc(self: Rc<Self>) -> Rc<dyn Any>192     fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any> { self }
as_any(&self) -> &dyn Any193     fn as_any(&self) -> &dyn Any { self }
as_any_mut(&mut self) -> &mut dyn Any194     fn as_any_mut(&mut self) -> &mut dyn Any { self }
195 }
196 
197 /// Extends `Downcast` to support `Sync` traits that thus support `Arc` downcasting as well.
198 pub trait DowncastSync: Downcast + Send + Sync {
199     /// Convert `Arc<Trait>` (where `Trait: Downcast`) to `Arc<Any>`. `Arc<Any>` can then be
200     /// further `downcast` into `Arc<ConcreteType>` where `ConcreteType` implements `Trait`.
into_any_arc(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>201     fn into_any_arc(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
202 }
203 
204 impl<T: Any + Send + Sync> DowncastSync for T {
into_any_arc(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>205     fn into_any_arc(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> { self }
206 }
207 
208 /// Adds downcasting support to traits that extend `downcast::Downcast` by defining forwarding
209 /// methods to the corresponding implementations on `std::any::Any` in the standard library.
210 ///
211 /// See https://users.rust-lang.org/t/how-to-create-a-macro-to-impl-a-provided-type-parametrized-trait/5289
212 /// for why this is implemented this way to support templatized traits.
213 #[macro_export(local_inner_macros)]
214 macro_rules! impl_downcast {
215     (@impl_full
216         $trait_:ident [$($param_types:tt)*]
217         for [$($forall_types:ident),*]
218         where [$($preds:tt)*]
219     ) => {
220         impl_downcast! {
221             @inject_where
222                 [impl<$($forall_types),*> dyn $trait_<$($param_types)*>]
223                 types [$($forall_types),*]
224                 where [$($preds)*]
225                 [{
226                     impl_downcast! { @impl_body $trait_ [$($param_types)*] }
227                 }]
228         }
229     };
230 
231     (@impl_full_sync
232         $trait_:ident [$($param_types:tt)*]
233         for [$($forall_types:ident),*]
234         where [$($preds:tt)*]
235     ) => {
236         impl_downcast! {
237             @inject_where
238                 [impl<$($forall_types),*> dyn $trait_<$($param_types)*>]
239                 types [$($forall_types),*]
240                 where [$($preds)*]
241                 [{
242                     impl_downcast! { @impl_body $trait_ [$($param_types)*] }
243                     impl_downcast! { @impl_body_sync $trait_ [$($param_types)*] }
244                 }]
245         }
246     };
247 
248     (@impl_body $trait_:ident [$($types:tt)*]) => {
249         /// Returns true if the trait object wraps an object of type `__T`.
250         #[inline]
251         pub fn is<__T: $trait_<$($types)*>>(&self) -> bool {
252             $crate::Downcast::as_any(self).is::<__T>()
253         }
254         /// Returns a boxed object from a boxed trait object if the underlying object is of type
255         /// `__T`. Returns the original boxed trait if it isn't.
256         #[inline]
257         pub fn downcast<__T: $trait_<$($types)*>>(
258             self: $crate::__alloc::boxed::Box<Self>
259         ) -> $crate::__std::result::Result<$crate::__alloc::boxed::Box<__T>, $crate::__alloc::boxed::Box<Self>> {
260             if self.is::<__T>() {
261                 Ok($crate::Downcast::into_any(self).downcast::<__T>().unwrap())
262             } else {
263                 Err(self)
264             }
265         }
266         /// Returns an `Rc`-ed object from an `Rc`-ed trait object if the underlying object is of
267         /// type `__T`. Returns the original `Rc`-ed trait if it isn't.
268         #[inline]
269         pub fn downcast_rc<__T: $trait_<$($types)*>>(
270             self: $crate::__alloc::rc::Rc<Self>
271         ) -> $crate::__std::result::Result<$crate::__alloc::rc::Rc<__T>, $crate::__alloc::rc::Rc<Self>> {
272             if self.is::<__T>() {
273                 Ok($crate::Downcast::into_any_rc(self).downcast::<__T>().unwrap())
274             } else {
275                 Err(self)
276             }
277         }
278         /// Returns a reference to the object within the trait object if it is of type `__T`, or
279         /// `None` if it isn't.
280         #[inline]
281         pub fn downcast_ref<__T: $trait_<$($types)*>>(&self) -> $crate::__std::option::Option<&__T> {
282             $crate::Downcast::as_any(self).downcast_ref::<__T>()
283         }
284         /// Returns a mutable reference to the object within the trait object if it is of type
285         /// `__T`, or `None` if it isn't.
286         #[inline]
287         pub fn downcast_mut<__T: $trait_<$($types)*>>(&mut self) -> $crate::__std::option::Option<&mut __T> {
288             $crate::Downcast::as_any_mut(self).downcast_mut::<__T>()
289         }
290     };
291 
292     (@impl_body_sync $trait_:ident [$($types:tt)*]) => {
293         /// Returns an `Arc`-ed object from an `Arc`-ed trait object if the underlying object is of
294         /// type `__T`. Returns the original `Arc`-ed trait if it isn't.
295         #[inline]
296         pub fn downcast_arc<__T: $trait_<$($types)*>>(
297             self: $crate::__alloc::sync::Arc<Self>,
298         ) -> $crate::__std::result::Result<$crate::__alloc::sync::Arc<__T>, $crate::__alloc::sync::Arc<Self>>
299             where __T: $crate::__std::any::Any + $crate::__std::marker::Send + $crate::__std::marker::Sync
300         {
301             if self.is::<__T>() {
302                 Ok($crate::DowncastSync::into_any_arc(self).downcast::<__T>().unwrap())
303             } else {
304                 Err(self)
305             }
306         }
307     };
308 
309     (@inject_where [$($before:tt)*] types [] where [] [$($after:tt)*]) => {
310         impl_downcast! { @as_item $($before)* $($after)* }
311     };
312 
313     (@inject_where [$($before:tt)*] types [$($types:ident),*] where [] [$($after:tt)*]) => {
314         impl_downcast! {
315             @as_item
316                 $($before)*
317                 where $( $types: $crate::__std::any::Any + 'static ),*
318                 $($after)*
319         }
320     };
321     (@inject_where [$($before:tt)*] types [$($types:ident),*] where [$($preds:tt)+] [$($after:tt)*]) => {
322         impl_downcast! {
323             @as_item
324                 $($before)*
325                 where
326                     $( $types: $crate::__std::any::Any + 'static, )*
327                     $($preds)*
328                 $($after)*
329         }
330     };
331 
332     (@as_item $i:item) => { $i };
333 
334     // No type parameters.
335     ($trait_:ident   ) => { impl_downcast! { @impl_full $trait_ [] for [] where [] } };
336     ($trait_:ident <>) => { impl_downcast! { @impl_full $trait_ [] for [] where [] } };
337     (sync $trait_:ident   ) => { impl_downcast! { @impl_full_sync $trait_ [] for [] where [] } };
338     (sync $trait_:ident <>) => { impl_downcast! { @impl_full_sync $trait_ [] for [] where [] } };
339     // Type parameters.
340     ($trait_:ident < $($types:ident),* >) => {
341         impl_downcast! { @impl_full $trait_ [$($types),*] for [$($types),*] where [] }
342     };
343     (sync $trait_:ident < $($types:ident),* >) => {
344         impl_downcast! { @impl_full_sync $trait_ [$($types),*] for [$($types),*] where [] }
345     };
346     // Type parameters and where clauses.
347     ($trait_:ident < $($types:ident),* > where $($preds:tt)+) => {
348         impl_downcast! { @impl_full $trait_ [$($types),*] for [$($types),*] where [$($preds)*] }
349     };
350     (sync $trait_:ident < $($types:ident),* > where $($preds:tt)+) => {
351         impl_downcast! { @impl_full_sync $trait_ [$($types),*] for [$($types),*] where [$($preds)*] }
352     };
353     // Associated types.
354     ($trait_:ident assoc $($atypes:ident),*) => {
355         impl_downcast! { @impl_full $trait_ [$($atypes = $atypes),*] for [$($atypes),*] where [] }
356     };
357     (sync $trait_:ident assoc $($atypes:ident),*) => {
358         impl_downcast! { @impl_full_sync $trait_ [$($atypes = $atypes),*] for [$($atypes),*] where [] }
359     };
360     // Associated types and where clauses.
361     ($trait_:ident assoc $($atypes:ident),* where $($preds:tt)+) => {
362         impl_downcast! { @impl_full $trait_ [$($atypes = $atypes),*] for [$($atypes),*] where [$($preds)*] }
363     };
364     (sync $trait_:ident assoc $($atypes:ident),* where $($preds:tt)+) => {
365         impl_downcast! { @impl_full_sync $trait_ [$($atypes = $atypes),*] for [$($atypes),*] where [$($preds)*] }
366     };
367     // Type parameters and associated types.
368     ($trait_:ident < $($types:ident),* > assoc $($atypes:ident),*) => {
369         impl_downcast! {
370             @impl_full
371                 $trait_ [$($types),*, $($atypes = $atypes),*]
372                 for [$($types),*, $($atypes),*]
373                 where []
374         }
375     };
376     (sync $trait_:ident < $($types:ident),* > assoc $($atypes:ident),*) => {
377         impl_downcast! {
378             @impl_full_sync
379                 $trait_ [$($types),*, $($atypes = $atypes),*]
380                 for [$($types),*, $($atypes),*]
381                 where []
382         }
383     };
384     // Type parameters, associated types, and where clauses.
385     ($trait_:ident < $($types:ident),* > assoc $($atypes:ident),* where $($preds:tt)+) => {
386         impl_downcast! {
387             @impl_full
388                 $trait_ [$($types),*, $($atypes = $atypes),*]
389                 for [$($types),*, $($atypes),*]
390                 where [$($preds)*]
391         }
392     };
393     (sync $trait_:ident < $($types:ident),* > assoc $($atypes:ident),* where $($preds:tt)+) => {
394         impl_downcast! {
395             @impl_full_sync
396                 $trait_ [$($types),*, $($atypes = $atypes),*]
397                 for [$($types),*, $($atypes),*]
398                 where [$($preds)*]
399         }
400     };
401     // Concretely-parametrized types.
402     (concrete $trait_:ident < $($types:ident),* >) => {
403         impl_downcast! { @impl_full $trait_ [$($types),*] for [] where [] }
404     };
405     (sync concrete $trait_:ident < $($types:ident),* >) => {
406         impl_downcast! { @impl_full_sync $trait_ [$($types),*] for [] where [] }
407     };
408     // Concretely-associated types types.
409     (concrete $trait_:ident assoc $($atypes:ident = $aty:ty),*) => {
410         impl_downcast! { @impl_full $trait_ [$($atypes = $aty),*] for [] where [] }
411     };
412     (sync concrete $trait_:ident assoc $($atypes:ident = $aty:ty),*) => {
413         impl_downcast! { @impl_full_sync $trait_ [$($atypes = $aty),*] for [] where [] }
414     };
415     // Concretely-parametrized types with concrete associated types.
416     (concrete $trait_:ident < $($types:ident),* > assoc $($atypes:ident = $aty:ty),*) => {
417         impl_downcast! { @impl_full $trait_ [$($types),*, $($atypes = $aty),*] for [] where [] }
418     };
419     (sync concrete $trait_:ident < $($types:ident),* > assoc $($atypes:ident = $aty:ty),*) => {
420         impl_downcast! { @impl_full_sync $trait_ [$($types),*, $($atypes = $aty),*] for [] where [] }
421     };
422 }
423 
424 
425 #[cfg(test)]
426 mod test {
427     macro_rules! test_mod {
428         (
429             $test_mod_name:ident,
430             trait $base_trait:path { $($base_impl:tt)* },
431             non_sync: { $($non_sync_def:tt)+ },
432             sync: { $($sync_def:tt)+ }
433         ) => {
434             test_mod! {
435                 $test_mod_name,
436                 trait $base_trait { $($base_impl:tt)* },
437                 type dyn $base_trait,
438                 non_sync: { $($non_sync_def)* },
439                 sync: { $($sync_def)* }
440             }
441         };
442 
443         (
444             $test_mod_name:ident,
445             trait $base_trait:path { $($base_impl:tt)* },
446             type $base_type:ty,
447             non_sync: { $($non_sync_def:tt)+ },
448             sync: { $($sync_def:tt)+ }
449         ) => {
450             mod $test_mod_name {
451                 test_mod!(
452                     @test
453                     $test_mod_name,
454                     test_name: test_non_sync,
455                     trait $base_trait { $($base_impl)* },
456                     type $base_type,
457                     { $($non_sync_def)+ },
458                     []);
459 
460                 test_mod!(
461                     @test
462                     $test_mod_name,
463                     test_name: test_sync,
464                     trait $base_trait { $($base_impl)* },
465                     type $base_type,
466                     { $($sync_def)+ },
467                     [{
468                         // Fail to convert Arc<Base> into Arc<Bar>.
469                         let arc: $crate::__alloc::sync::Arc<$base_type> = $crate::__alloc::sync::Arc::new(Foo(42));
470                         let res = arc.downcast_arc::<Bar>();
471                         assert!(res.is_err());
472                         let arc = res.unwrap_err();
473                         // Convert Arc<Base> into Arc<Foo>.
474                         assert_eq!(
475                             42, arc.downcast_arc::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
476                     }]);
477             }
478         };
479 
480         (
481             @test
482             $test_mod_name:ident,
483             test_name: $test_name:ident,
484             trait $base_trait:path { $($base_impl:tt)* },
485             type $base_type:ty,
486             { $($def:tt)+ },
487             [ $($more_tests:block)* ]
488         ) => {
489             #[test]
490             fn $test_name() {
491                 #[allow(unused_imports)]
492                 use super::super::{Downcast, DowncastSync};
493 
494                 // Should work even if standard objects (especially those in the prelude) are
495                 // aliased to something else.
496                 #[allow(dead_code)] struct Any;
497                 #[allow(dead_code)] struct Arc;
498                 #[allow(dead_code)] struct Box;
499                 #[allow(dead_code)] struct Option;
500                 #[allow(dead_code)] struct Result;
501                 #[allow(dead_code)] struct Rc;
502                 #[allow(dead_code)] struct Send;
503                 #[allow(dead_code)] struct Sync;
504 
505                 // A trait that can be downcast.
506                 $($def)*
507 
508                 // Concrete type implementing Base.
509                 #[derive(Debug)]
510                 struct Foo(u32);
511                 impl $base_trait for Foo { $($base_impl)* }
512                 #[derive(Debug)]
513                 struct Bar(f64);
514                 impl $base_trait for Bar { $($base_impl)* }
515 
516                 // Functions that can work on references to Base trait objects.
517                 fn get_val(base: &$crate::__alloc::boxed::Box<$base_type>) -> u32 {
518                     match base.downcast_ref::<Foo>() {
519                         Some(val) => val.0,
520                         None => 0
521                     }
522                 }
523                 fn set_val(base: &mut $crate::__alloc::boxed::Box<$base_type>, val: u32) {
524                     if let Some(foo) = base.downcast_mut::<Foo>() {
525                         foo.0 = val;
526                     }
527                 }
528 
529                 let mut base: $crate::__alloc::boxed::Box<$base_type> = $crate::__alloc::boxed::Box::new(Foo(42));
530                 assert_eq!(get_val(&base), 42);
531 
532                 // Try sequential downcasts.
533                 if let Some(foo) = base.downcast_ref::<Foo>() {
534                     assert_eq!(foo.0, 42);
535                 } else if let Some(bar) = base.downcast_ref::<Bar>() {
536                     assert_eq!(bar.0, 42.0);
537                 }
538 
539                 set_val(&mut base, 6*9);
540                 assert_eq!(get_val(&base), 6*9);
541 
542                 assert!(base.is::<Foo>());
543 
544                 // Fail to convert Box<Base> into Box<Bar>.
545                 let res = base.downcast::<Bar>();
546                 assert!(res.is_err());
547                 let base = res.unwrap_err();
548                 // Convert Box<Base> into Box<Foo>.
549                 assert_eq!(
550                     6*9, base.downcast::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
551 
552                 // Fail to convert Rc<Base> into Rc<Bar>.
553                 let rc: $crate::__alloc::rc::Rc<$base_type> = $crate::__alloc::rc::Rc::new(Foo(42));
554                 let res = rc.downcast_rc::<Bar>();
555                 assert!(res.is_err());
556                 let rc = res.unwrap_err();
557                 // Convert Rc<Base> into Rc<Foo>.
558                 assert_eq!(
559                     42, rc.downcast_rc::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
560 
561                 $($more_tests)*
562             }
563         };
564         (
565             $test_mod_name:ident,
566             trait $base_trait:path { $($base_impl:tt)* },
567             non_sync: { $($non_sync_def:tt)+ },
568             sync: { $($sync_def:tt)+ }
569         ) => {
570             test_mod! {
571                 $test_mod_name,
572                 trait $base_trait { $($base_impl:tt)* },
573                 type $base_trait,
574                 non_sync: { $($non_sync_def)* },
575                 sync: { $($sync_def)* }
576             }
577         };
578 
579     }
580 
581     test_mod!(non_generic, trait Base {},
582         non_sync: {
583             trait Base: Downcast {}
584             impl_downcast!(Base);
585         },
586         sync: {
587             trait Base: DowncastSync {}
588             impl_downcast!(sync Base);
589         });
590 
591     test_mod!(generic, trait Base<u32> {},
592         non_sync: {
593             trait Base<T>: Downcast {}
594             impl_downcast!(Base<T>);
595         },
596         sync: {
597             trait Base<T>: DowncastSync {}
598             impl_downcast!(sync Base<T>);
599         });
600 
601     test_mod!(constrained_generic, trait Base<u32> {},
602         non_sync: {
603             trait Base<T: Copy>: Downcast {}
604             impl_downcast!(Base<T> where T: Copy);
605         },
606         sync: {
607             trait Base<T: Copy>: DowncastSync {}
608             impl_downcast!(sync Base<T> where T: Copy);
609         });
610 
611     test_mod!(associated,
612         trait Base { type H = f32; },
613         type dyn Base<H=f32>,
614         non_sync: {
615             trait Base: Downcast { type H; }
616             impl_downcast!(Base assoc H);
617         },
618         sync: {
619             trait Base: DowncastSync { type H; }
620             impl_downcast!(sync Base assoc H);
621         });
622 
623     test_mod!(constrained_associated,
624         trait Base { type H = f32; },
625         type dyn Base<H=f32>,
626         non_sync: {
627             trait Base: Downcast { type H: Copy; }
628             impl_downcast!(Base assoc H where H: Copy);
629         },
630         sync: {
631             trait Base: DowncastSync { type H: Copy; }
632             impl_downcast!(sync Base assoc H where H: Copy);
633         });
634 
635     test_mod!(param_and_associated,
636         trait Base<u32> { type H = f32; },
637         type dyn Base<u32, H=f32>,
638         non_sync: {
639             trait Base<T>: Downcast { type H; }
640             impl_downcast!(Base<T> assoc H);
641         },
642         sync: {
643             trait Base<T>: DowncastSync { type H; }
644             impl_downcast!(sync Base<T> assoc H);
645         });
646 
647     test_mod!(constrained_param_and_associated,
648         trait Base<u32> { type H = f32; },
649         type dyn Base<u32, H=f32>,
650         non_sync: {
651             trait Base<T: Clone>: Downcast { type H: Copy; }
652             impl_downcast!(Base<T> assoc H where T: Clone, H: Copy);
653         },
654         sync: {
655             trait Base<T: Clone>: DowncastSync { type H: Copy; }
656             impl_downcast!(sync Base<T> assoc H where T: Clone, H: Copy);
657         });
658 
659     test_mod!(concrete_parametrized, trait Base<u32> {},
660         non_sync: {
661             trait Base<T>: Downcast {}
662             impl_downcast!(concrete Base<u32>);
663         },
664         sync: {
665             trait Base<T>: DowncastSync {}
666             impl_downcast!(sync concrete Base<u32>);
667         });
668 
669     test_mod!(concrete_associated,
670         trait Base { type H = u32; },
671         type dyn Base<H=u32>,
672         non_sync: {
673             trait Base: Downcast { type H; }
674             impl_downcast!(concrete Base assoc H=u32);
675         },
676         sync: {
677             trait Base: DowncastSync { type H; }
678             impl_downcast!(sync concrete Base assoc H=u32);
679         });
680 
681     test_mod!(concrete_parametrized_associated,
682         trait Base<u32> { type H = f32; },
683         type dyn Base<u32, H=f32>,
684         non_sync: {
685             trait Base<T>: Downcast { type H; }
686             impl_downcast!(concrete Base<u32> assoc H=f32);
687         },
688         sync: {
689             trait Base<T>: DowncastSync { type H; }
690             impl_downcast!(sync concrete Base<u32> assoc H=f32);
691         });
692 }
693