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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
pub use ;
/// A type that can be turned into the enum of its sealed trait.
///
/// [`enumerate`] implements this for every permitted type, and makes
/// `Enumerable<AnyShape>` a supertrait of the sealed trait. Naming the enum in
/// the bound is what lets a caller reach it through the trait alone:
///
/// ```
/// use closed_trait::{enumerate, sealed};
///
/// pub struct Square { pub side: i32 }
/// pub struct Circle { pub radius: i32 }
///
/// #[enumerate]
/// #[sealed(Square, Circle)]
/// pub trait Shape {}
///
/// impl Shape for Square {}
/// impl Shape for Circle {}
///
/// /// Generic over the trait, yet able to match exhaustively.
/// fn corners<S: Shape>(shape: S) -> u32 {
/// match shape.into_enum() {
/// AnyShape::Square(_) => 4,
/// AnyShape::Circle(_) => 0,
/// }
/// }
///
/// fn main() {
/// assert_eq!(corners(Square { side: 1 }), 4);
/// assert_eq!(corners(Circle { radius: 1 }), 0);
/// }
/// ```
///
/// Note that `Enumerable` did not have to be imported above: the supertrait
/// bound brings `into_enum` into scope through `S: Shape`. Calling it on a
/// concrete type rather than a generic one does need the import.
///
/// The enum is a type *parameter* rather than an associated type so that one
/// type can belong to several sealed traits at once, since an associated type could
/// only be chosen once per implementor. The cost is that `into_enum` on a
/// concrete type belonging to more than one needs the target spelled out, by
/// annotation or turbofish. `From` sidesteps that, since the enum is named by
/// the conversion itself.
///
/// `From` is implemented alongside it in the other direction, so
/// `AnyShape::from(square)` and `square.into()` work too.
/// A type that can lend itself to the *borrowing* enum of its sealed trait.
///
/// [`enumerate`] implements this for every permitted type and makes
/// `for<'a> EnumerableRef<'a, AnyShapeRef<'a>>` a supertrait. The
/// lifetime is a parameter of the trait rather than of the method, so the
/// higher-ranked bound is nameable in the supertrait list, which is what lets
/// a caller reach the enum from a plain `&S`:
///
/// ```
/// use closed_trait::{enumerate, sealed};
///
/// pub struct Square { pub side: i32 }
/// pub struct Circle { pub radius: i32 }
///
/// #[enumerate(match_any)]
/// #[sealed(Square, Circle)]
/// pub trait Shape {}
///
/// impl Shape for Square {}
/// impl Shape for Circle {}
///
/// /// Takes a reference, yet still matches exhaustively.
/// fn corners<S: Shape>(shape: &S) -> u32 {
/// match shape.as_enum_ref() {
/// AnyShapeRef::Square(_) => 4,
/// AnyShapeRef::Circle(_) => 0,
/// }
/// }
///
/// fn main() {
/// assert_eq!(corners(&Square { side: 1 }), 4);
/// assert_eq!(corners(&Circle { radius: 1 }), 0);
/// }
/// ```
///
/// [`Enumerable`] cannot do this: `into_enum` takes `self`, so reaching the
/// owned enum means owning the value. The borrowing enum is also the cheaper
/// one to pass, being a pointer and a discriminant rather than as large as the
/// biggest permitted type.
/// A type that can lend itself *mutably* to the borrowing enum of its sealed
/// trait.
///
/// The counterpart of [`EnumerableRef`], and reached from a `&mut S` the same
/// way:
///
/// ```
/// use closed_trait::{enumerate, sealed};
///
/// pub struct Square { pub side: i32 }
/// pub struct Circle { pub radius: i32 }
///
/// #[enumerate]
/// #[sealed(Square, Circle)]
/// pub trait Shape {
/// fn grow(&mut self);
/// }
///
/// impl Shape for Square { fn grow(&mut self) { self.side += 1; } }
/// impl Shape for Circle { fn grow(&mut self) { self.radius += 1; } }
///
/// fn grow_twice<S: Shape>(shape: &mut S) {
/// match shape.as_enum_mut() {
/// AnyShapeMut::Square(s) => { s.grow(); s.grow(); }
/// AnyShapeMut::Circle(c) => { c.grow(); c.grow(); }
/// }
/// }
///
/// fn main() {
/// let mut square = Square { side: 1 };
/// grow_twice(&mut square);
/// assert_eq!(square.side, 3);
/// }
/// ```
///
/// Unlike the shared enum this one is neither `Clone` nor `Copy`, a unique
/// reference being neither.