trait_cast/
decl_macro.rs

1/// Declarative macro for automatic implementation of `TraitcastableAny` (and `TraitcastableTo`).
2/// Generally not for direct invocation, but rather used by the proc-macro `make_trait_castable`.
3///
4/// Syntax: `<concrete struct/enum/union> => (<target traits>, ...)`
5///
6/// # Usage
7/// ```ignore
8/// make_trait_castable_decl! {
9///     SrcStruct1 => (DstTrait1, DstTrait2),
10///     SrcStruct2 => (DstTrait3, DstTrait4),
11/// }
12/// ```
13#[macro_export]
14macro_rules! make_trait_castable_decl {
15  ($($source:ty => ($($target:path),* $(,)?)),+$(,)?) => {
16    $(
17      $(
18        impl $crate::TraitcastableTo<dyn $target> for $source {
19          const METADATA: ::core::ptr::DynMetadata<dyn $target> = {
20            let self_ptr: *const $source = ::core::ptr::null::<$source>();
21            let dyn_ptr: *const dyn $target = self_ptr as _;
22
23            dyn_ptr.to_raw_parts().1
24          };
25        }
26      )*
27      // Safety:
28      // All returned `TraitcastTarget`s are valid for $source
29      unsafe impl $crate::TraitcastableAny for $source {
30        fn traitcast_targets(&self) -> &[$crate::TraitcastTarget] {
31          #[allow(clippy::unused_unit)]
32          const TARGETS_LEN: usize = {
33            let a:&[()] = &[$({
34              let _: &dyn $target;
35              ()
36            },)*];
37            a.len()
38          };
39          const TARGETS: [$crate::TraitcastTarget; TARGETS_LEN] = {
40            #[allow(unused_mut)]
41            let mut targets : [$crate::TraitcastTarget; TARGETS_LEN] = [
42              $(
43                $crate::TraitcastTarget::from::<$source, dyn $target>(),
44              )*
45            ];
46            targets
47          };
48          &TARGETS
49        }
50      }
51    )+
52  };
53}