1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use TokenStream;
use ;
/// Derive `From<Self>` for every enum mentioned in an
/// `#[ancestors(Parent::Variant)]` attribute.
///
/// For each `#[ancestors(Parent::Variant)]` attribute on the deriving type,
/// the macro emits:
///
/// ```text
/// impl ::core::convert::From<Self> for Parent {
/// fn from(child: Self) -> Parent {
/// Parent::Variant(::core::convert::Into::into(child))
/// }
/// }
/// ```
///
/// The body wraps the child via `Into::into`, so any compatible
/// `From`/`Into` chain already in scope is reused. List every parent the
/// type needs to reach directly; the macro does **not** transitively walk
/// the `#[ancestors(...)]` attributes on intermediate enums.
///
/// # Example
///
/// ```ignore
/// use enum_tree::{EnumFrom, IntoAncestors};
///
/// #[derive(EnumFrom)]
/// enum Fermion
/// {
/// Quark(#[enum_from(from)] Quark),
/// Charged(#[enum_from(from)] ChargedLepton),
/// Neutrino(#[enum_from(from)] Neutrino),
/// }
///
/// #[derive(EnumFrom)]
/// enum Quark
/// {
/// Up(#[enum_from(from)] UpQuark),
/// Charm(#[enum_from(from)] CharmQuark),
/// }
///
/// struct ChargedLepton;
/// struct Neutrino;
///
/// // Each leaf lists every ancestor it must reach directly.
/// #[derive(IntoAncestors)]
/// #[ancestors(Quark::Charm)]
/// #[ancestors(Fermion::Quark)]
/// struct CharmQuark;
///
/// #[derive(IntoAncestors)]
/// #[ancestors(Quark::Up)]
/// #[ancestors(Fermion::Quark)]
/// struct UpQuark;
///
/// let _: Quark = CharmQuark.into();
/// let _: Fermion = CharmQuark.into();
/// let _: Fermion = UpQuark.into();
/// ```
///
/// # Limitations
///
/// The macro does not have access to the parent enum's definition, so it
/// cannot emit a `where Self: ::core::convert::Into<...>` bound: the
/// payload type of `Parent::Variant` is unknown at derive time. If the
/// caller has not supplied a compatible `From`/`Into` chain, the
/// resulting type error appears inside the generated function body
/// instead of on the impl header.
/// Create a const array with all possible values of an enum.
/// Target must be an `enum`, and each variant of the target must be of *nested unit type*.
/// A variant is of nested unit type if it is either:
///
/// a) a unit variant, or
/// b) an singleton tuple variant, whose inner type is compatible.
///
/// Variants annotated with `#[enum_tree(skip)]` are excluded.
/// Derive From implementations for an enum from variants.