[−][src]Macro transitive_from::hierarchy
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 From
s 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);