[][src]Macro transitive_from::hierarchy

macro_rules! hierarchy {
    ($($root:ty $({
        $($child:ty $({
            $($grandchildren_parsed_recursively:tt)*
        })?),* $(,)?
    })?),* $(,)?) => { ... };
}

Helper macro to create transitive From implementations.

This macro can work on tree-shaped hierarchies of implementations impl From<Child> for Parent along the tree edges. It will produce new From implementations along paths towards the root by chaining From::from() calls along the edges. There must not be any pre-existing impl Froms for anything but the immediate edges.

For further details, study the example below.

The syntax supports arbitrary type expressions where the example just uses simple names like A, B, C, etc; the macro does however not produce any generic implementations. Inside of each { } block, a trailing comma is optional.

Examples

// Here’s a drawing of an example hierarchy.
//
//            ┌─ E
//      ┌─ B ─┤     ┌─ J
//      │     └─ F ─┤
//      │           └─ K
//   A ─┼─ C ─── G
//      │
//      │     ┌─ H
//      └─ D ─┤
//            └─ I ─── L
//
// For example, all these types could be error types and we
// would like to fully support upcasting with the `?` operator
// from anywhere to anywhere in this hierarchy.
struct A;
struct B;
struct C;
struct D;
struct E;
struct F;
struct G;
struct H;
struct I;
struct J;
struct K;
struct L;

// We need to provide implementation for all the tree edges
// (all the immediate "child -> parent" steps) manually,
// or by some other means. In this example we use a small macro
// to save some boilerplate.
macro_rules! impl_From {
    (<$B:ident> for $A:ident) => {
        impl From<$B> for $A {
            fn from(_: $B) -> $A {
                $A
            }
        }
    }
}
impl_From!(<B> for A);
impl_From!(<C> for A);
impl_From!(<D> for A);
impl_From!(<E> for B);
impl_From!(<F> for B);
impl_From!(<G> for C);
impl_From!(<H> for D);
impl_From!(<I> for D);
impl_From!(<J> for F);
impl_From!(<K> for F);
impl_From!(<L> for I);

// Now, to produce all the remaining (transitive) implementations
// and complete the hierarchy, call the macro like this:
transitive_from::hierarchy! {
    A {
        B {
            E,
            F { J, K },
        },
        C { G },
        D {
            H,
            I { L },
        },
    }
}
// Note how the syntax resembles the tree drawn at the top of this example.

// Finally, a few demonstration/test cases:
A::from(K);
A::from(E);
B::from(K);
D::from(L);
A::from(L);