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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
//! Implements a trait for an enum by forwarding to whichever variant it holds.
//!
//! `#[dispatchable]` goes on the trait, in the crate that owns it.
//! `#[dispatch(Trait)]` goes on an enum whose variants each hold one value
//! implementing the trait, in any crate. The enum then implements the trait
//! with one `match` per method, each arm a fully qualified call into the
//! variant's payload, and gets a `From<Payload>` impl per variant.
//!
//! ```
//! // In the crate that owns the trait.
//! #[whichever::dispatchable]
//! pub trait Shape {
//! fn area(&self) -> u32;
//! fn name(&self) -> &'static str {
//! "shape"
//! }
//! }
//!
//! pub struct Square(pub u32);
//! pub struct Rect(pub u32, pub u32);
//!
//! impl Shape for Square {
//! fn area(&self) -> u32 {
//! self.0 * self.0
//! }
//! fn name(&self) -> &'static str {
//! "square"
//! }
//! }
//!
//! impl Shape for Rect {
//! fn area(&self) -> u32 {
//! self.0 * self.1
//! }
//! }
//!
//! // In any crate that owns an enum over implementors.
//! #[whichever::dispatch(Shape)]
//! pub enum AnyShape {
//! Square(Square),
//! Rect(Rect),
//! }
//!
//! fn main() {
//! let square: AnyShape = Square(3).into();
//! let rect: AnyShape = Rect(2, 5).into();
//! assert_eq!((square.area(), square.name()), (9, "square"));
//! assert_eq!((rect.area(), rect.name()), (10, "shape"));
//! }
//! ```
//!
//! # What is generated
//!
//! For the enum above, `#[dispatch(Shape)]` expands to the impl a careful
//! hand would write, plus `#[inline]` and the conversions:
//!
//! ```rust,ignore
//! impl Shape for AnyShape {
//! #[inline]
//! fn area(&self) -> u32 {
//! match self {
//! AnyShape::Square(inner) => <Square as Shape>::area(inner),
//! AnyShape::Rect(inner) => <Rect as Shape>::area(inner),
//! }
//! }
//! #[inline]
//! fn name(&self) -> &'static str {
//! match self {
//! AnyShape::Square(inner) => <Square as Shape>::name(inner),
//! AnyShape::Rect(inner) => <Rect as Shape>::name(inner),
//! }
//! }
//! }
//!
//! impl From<Square> for AnyShape { /* .. */ }
//! impl From<Rect> for AnyShape { /* .. */ }
//! ```
//!
//! Default methods are always forwarded, so a variant's override is never
//! hidden by the trait's default at the enum level. The calls are fully
//! qualified, so an inherent method on a payload with the same name as a
//! trait method does not take over. There is no trait object, no closure
//! and no conversion in the arms unless an option asks for one.
//!
//! # Options
//!
//! All options follow the trait path in `#[dispatch(..)]`:
//!
//! - `Name = Type` fixes the associated type `Name` instead of taking it
//! from the first variant. A method returning `Self::Name` is then
//! converted with [`Into`], and one returning `Result<_, Self::Name>` with
//! `map_err(Into::into)`, so variants whose own type converts into the
//! named one can share the enum. See [associated types](#associated-types).
//! - `mismatch(method = expr, ..)` gives the result of `method` when its
//! `Self` arguments hold a different variant than `self`. The trait author
//! can decide this once instead, with `#[dispatch(mismatch = expr)]` on
//! the method. See [`Self` arguments](#self-arguments).
//! - `from = false` suppresses the `From<Payload>` impls.
//! - `try_from = true` adds `TryFrom<Enum> for Payload` for every payload
//! type, with the enum itself as the error, so a mismatch hands the value
//! back.
//!
//! One option goes on a variant: `#[dispatch(deref)]` calls the trait on
//! what the payload dereferences to, so `Box<T>`, `Rc<T>`, `Arc<T>`, `&T`
//! and `&mut T` payloads dispatch like a plain `T`. See
//! [dereferenced payloads](#dereferenced-payloads).
//!
//! Several traits are dispatched by repeating the attribute, one trait per
//! attribute; a supertrait is just one more attribute:
//!
//! ```rust,ignore
//! #[whichever::dispatch(Shape)]
//! #[whichever::dispatch(Drawable)]
//! pub enum AnyShape { /* .. */ }
//! ```
//!
//! # Semantics
//!
//! | Trait item | Enum impl |
//! | --- | --- |
//! | `type X;` | `type X = <FirstVariant as Trait>::X;`, or the `X = Type` option. Every other variant is checked to agree; a disagreement is reported on that variant. |
//! | `const N: T;` | `const N: T = <FirstVariant as Trait>::N;` |
//! | method with a receiver | A `match` over the variants calling `<Payload as Trait>::method(payload, args..)`. |
//! | default body | Ignored: the method is forwarded like any other. |
//! | `async fn` | Each arm is awaited. |
//! | `unsafe fn` | Each call is wrapped in `unsafe { }`. |
//! | argument `Self`, `&Self`, `&mut Self` | Matched on the same variant as `self`; different variants give the `mismatch` expression. |
//! | return `Self` | Wrapped back into the same variant; `Option<Self>` and `Result<Self, E>` are mapped. |
//! | return `Self::X` with `X` overridden | Converted with `Into`; `Result<_, Self::X>` with `map_err(Into::into)`. |
//! | method without a receiver | Left to the trait's default body; an error when there is none. |
//! | `#[cfg]` on a method or variant | Carried onto the generated method or arm. |
//! | `#[inline]` | Added to every generated method unless the trait method carries its own. |
//!
//! # Generics
//!
//! A generic trait is dispatched at a concrete instantiation, named on the
//! enum: `#[dispatch(Encoder<Json>)]`. Type, lifetime and const parameters
//! are substituted in every signature, and a projection such as `F::Value`
//! becomes `<Json as Format>::Value` when `F` has exactly one bound. The
//! enum itself may be generic; its parameters, bounds and `where` clause
//! carry into the impl.
//!
//! # `Self` arguments
//!
//! A method such as `fn congruent(&self, other: &Self) -> bool` compares two
//! values of the enum. The generated method matches both on the same variant
//! and calls the payload's method; for two different variants it returns the
//! expression given by `#[dispatch(mismatch = false)]` on the trait method,
//! or by `mismatch(congruent = false)` on the enum. Without one the expansion
//! fails with an error naming the method. Only `Self`, `&Self` and
//! `&mut Self` are accepted; a `Self` nested in another type
//! (`Option<&Self>`) is an error.
//!
//! # Associated types
//!
//! Without an override the enum takes each associated type from its first
//! variant, and a hidden check asserts that every other variant uses the
//! same type, with the error on the variant that differs. With
//! `Error = StorageError` the enum's type is `StorageError`, and each
//! variant's own error type only has to implement `Into<StorageError>`:
//!
//! ```
//! #[whichever::dispatchable]
//! pub trait Storage {
//! type Error;
//! fn load(&self, key: &str) -> Result<u32, Self::Error>;
//! }
//!
//! #[derive(Debug, PartialEq)]
//! pub struct StorageError(pub String);
//!
//! pub struct Memory;
//! pub struct Disk;
//!
//! impl Storage for Memory {
//! type Error = StorageError;
//! fn load(&self, key: &str) -> Result<u32, StorageError> {
//! Ok(key.len() as u32)
//! }
//! }
//!
//! impl Storage for Disk {
//! type Error = &'static str;
//! fn load(&self, key: &str) -> Result<u32, &'static str> {
//! Err("offline")
//! }
//! }
//!
//! impl From<&'static str> for StorageError {
//! fn from(message: &'static str) -> Self {
//! StorageError(message.to_owned())
//! }
//! }
//!
//! #[whichever::dispatch(Storage, Error = StorageError)]
//! pub enum AnyStorage {
//! Memory(Memory),
//! Disk(Disk),
//! }
//!
//! fn main() {
//! let disk: AnyStorage = Disk.into();
//! assert_eq!(disk.load("answer"), Err(StorageError("offline".to_owned())));
//! }
//! ```
//!
//! # Dereferenced payloads
//!
//! A variant marked `#[dispatch(deref)]` holds its value behind a pointer or
//! a reference. The trait is called on `<Payload as Deref>::Target`, with
//! the receiver and any `Self` argument dereferenced to match: `&**inner`
//! for `&self`, `&mut **inner` for `&mut self` (the payload must implement
//! `DerefMut`), `*inner` for `self` (a `Box` moves out, a reference cannot).
//! A method returning `Self` cannot wrap its result back into such a
//! payload, so it is rejected for a `deref` variant.
//!
//! ```
//! use std::rc::Rc;
//!
//! #[whichever::dispatchable]
//! pub trait Area {
//! fn area(&self) -> u32;
//! }
//!
//! pub struct Square(pub u32);
//!
//! impl Area for Square {
//! fn area(&self) -> u32 {
//! self.0 * self.0
//! }
//! }
//!
//! #[whichever::dispatch(Area)]
//! pub enum Shape<'a> {
//! #[dispatch(deref)]
//! Boxed(Box<Square>),
//! #[dispatch(deref)]
//! Shared(Rc<Square>),
//! #[dispatch(deref)]
//! Borrowed(&'a Square),
//! Plain(Square),
//! }
//!
//! fn main() {
//! let square = Square(3);
//! assert_eq!(Shape::Boxed(Box::new(Square(2))).area(), 4);
//! assert_eq!(Shape::Borrowed(&square).area(), 9);
//! }
//! ```
//!
//! # Inherent methods
//!
//! An enum often needs methods of its own that only some variants can
//! answer. `#[dispatch]` on an inherent `impl` block of a dispatch enum
//! forwards each method marked `#[dispatch(..)]` to the named variants'
//! method of the same name, and the body is what every other variant
//! returns. `*` names every variant, and the method then has no body:
//!
//! ```
//! #[whichever::dispatchable]
//! pub trait Shape {
//! fn area(&self) -> u32;
//! }
//!
//! pub struct Circle(pub u32);
//! pub struct Square(pub u32);
//! # impl Shape for Circle { fn area(&self) -> u32 { 3 * self.0 * self.0 } }
//! # impl Shape for Square { fn area(&self) -> u32 { self.0 * self.0 } }
//!
//! impl Circle {
//! pub fn radius(&self) -> u32 {
//! self.0
//! }
//! pub fn describe(&self) -> String {
//! format!("circle {}", self.0)
//! }
//! }
//!
//! impl Square {
//! pub fn describe(&self) -> String {
//! format!("square {}", self.0)
//! }
//! }
//!
//! #[whichever::dispatch(Shape)]
//! pub enum AnyShape {
//! Circle(Circle),
//! Square(Square),
//! }
//!
//! #[whichever::dispatch]
//! impl AnyShape {
//! /// Only circles have a radius.
//! #[dispatch(Circle, with = Some)]
//! pub fn radius(&self) -> Option<u32> {
//! None
//! }
//!
//! #[dispatch(*)]
//! pub fn describe(&self) -> String;
//! }
//!
//! fn main() {
//! let square: AnyShape = Square(2).into();
//! assert_eq!(square.radius(), None);
//! assert_eq!(square.describe(), "square 2");
//! }
//! ```
//!
//! `with = path` wraps each forwarded result in a call to `path` (`Some`
//! above), `call = name` forwards to a payload method of another name, and
//! methods without the attribute are left alone. The enum keeps its
//! definition in a crate-local macro for this, so the `impl` block has to be
//! in the enum's crate, which inherent impls are anyway. A bare `#[dispatch]`
//! on an enum registers it without dispatching a trait.
//!
//! # Across crates
//!
//! `#[dispatchable]` emits the trait unchanged plus a hidden exported macro
//! carrying the trait's tokens, re-exported under the trait's own name
//! (macros live in their own namespace, so `use shapes::Shape;` imports
//! both). `#[dispatch(Shape)]` invokes that macro, which hands the trait
//! and the enum to a hidden proc macro that writes the impl. Nothing is
//! cached between expansions, so the two attributes work across crates, in
//! any order, and under rust-analyzer. Both crates depend on `whichever`; a
//! renamed dependency is fine.
//!
//! The types named in the trait's signatures are written into the enum's
//! module, so they must be in scope there, exactly as for a hand-written
//! impl. Paths starting with `crate::` are rewritten to the trait's crate;
//! `super::` and `self::` paths cannot be and must not appear in a
//! dispatchable trait's signatures.
//!
//! # Requirements and limits
//!
//! - Every variant holds exactly one unnamed field, `Name(Payload)`, and
//! every payload implements the trait. A payload type used by two variants
//! gets no `From` impl.
//! - A method without a receiver needs a default body; the enum uses it.
//! - Return-position `impl Trait` cannot be dispatched by a `match`: every
//! variant would return a different opaque type.
//! - Generic associated types and `self: Type` receivers are not supported.
//! - Associated consts are taken from the first variant without a check.
//!
//! "cannot find macro `Shape` in this scope" at the enum means the trait is
//! not marked `#[dispatchable]`, or the trait (which carries the macro) is
//! not imported where the enum is.
//!
//! The crate is `no_std`: the generated code names only `core` items. The
//! minimum supported Rust version is 1.88.
pub use ;