auto_enums/
lib.rs

1// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3/*!
4A library for to allow multiple return types by automatically generated enum.
5
6This crate is a procedural macro implementation of the features discussions
7in [rust-lang/rfcs#2414]. This idea is also known as
8["Anonymous sum types"][rust-lang/rfcs#294].
9
10This library provides the following attribute macros:
11
12- `#[auto_enum]`
13
14  Parses syntax, creates the enum, inserts variants, and passes specified
15  traits to `#[enum_derive]`.
16
17- `#[enum_derive]`
18
19  Implements specified traits to the enum.
20
21# `#[auto_enum]`
22
23`#[auto_enum]`'s basic feature is to wrap the value returned by the obvious
24branches (`match`, `if`, `return`, etc..) by an enum that implemented the
25specified traits.
26
27```rust
28use auto_enums::auto_enum;
29
30#[auto_enum(Iterator)]
31fn foo(x: i32) -> impl Iterator<Item = i32> {
32    match x {
33        0 => 1..10,
34        _ => vec![5, 10].into_iter(),
35    }
36}
37```
38
39`#[auto_enum]` generates code in two stages.
40
41First, `#[auto_enum]` will do the following.
42
43- parses syntax
44- creates the enum
45- inserts variants
46
47Code like this will be generated:
48
49```rust
50fn foo(x: i32) -> impl Iterator<Item = i32> {
51    #[::auto_enums::enum_derive(Iterator)]
52    enum __Enum1<__T1, __T2> {
53        __T1(__T1),
54        __T2(__T2),
55    }
56
57    match x {
58        0 => __Enum1::__T1(1..10),
59        _ => __Enum1::__T2(vec![5, 10].into_iter()),
60    }
61}
62```
63
64Next, `#[enum_derive]` implements the specified traits.
65
66<details>
67<summary>Code like this will be generated:</summary>
68
69```rust
70fn foo(x: i32) -> impl Iterator<Item = i32> {
71    enum __Enum1<__T1, __T2> {
72        __T1(__T1),
73        __T2(__T2),
74    }
75
76    impl<__T1, __T2> ::core::iter::Iterator for __Enum1<__T1, __T2>
77    where
78        __T1: ::core::iter::Iterator,
79        __T2: ::core::iter::Iterator<Item = <__T1 as ::core::iter::Iterator>::Item>,
80    {
81        type Item = <__T1 as ::core::iter::Iterator>::Item;
82        #[inline]
83        fn next(&mut self) -> ::core::option::Option<Self::Item> {
84            match self {
85                __Enum1::__T1(x) => x.next(),
86                __Enum1::__T2(x) => x.next(),
87            }
88        }
89        #[inline]
90        fn size_hint(&self) -> (usize, ::core::option::Option<usize>) {
91            match self {
92                __Enum1::__T1(x) => x.size_hint(),
93                __Enum1::__T2(x) => x.size_hint(),
94            }
95        }
96    }
97
98    match x {
99        0 => __Enum1::__T1(1..10),
100        _ => __Enum1::__T2(vec![5, 10].into_iter()),
101    }
102}
103```
104
105</details>
106<br>
107
108## Nested arms/branches
109
110`#[auto_enum]` can also parse nested arms/branches by using the `#[nested]`
111attribute.
112
113```rust
114use auto_enums::auto_enum;
115
116#[auto_enum(Iterator)]
117fn foo(x: i32) -> impl Iterator<Item = i32> {
118    match x {
119        0 => 1..10,
120        #[nested]
121        _ => match x {
122            1 => vec![5, 10].into_iter(),
123            _ => 0..=x,
124        },
125    }
126}
127```
128
129`#[nested]` can be used basically in the same place as `#[auto_enum]`,
130except that `#[nested]` cannot be used in functions.
131
132## Recursion
133
134If an error due to recursion occurs, you need to box branches where recursion occurs.
135
136```rust
137use auto_enums::auto_enum;
138
139struct Type {
140    child: Vec<Type>,
141}
142
143impl Type {
144    #[auto_enum(Iterator)]
145    fn method(&self) -> impl Iterator<Item = ()> + '_ {
146        if self.child.is_empty() {
147            Some(()).into_iter()
148        } else {
149            // Boxing is only needed on branches where recursion occurs.
150            Box::new(self.child.iter().flat_map(|c| c.method())) as Box<dyn Iterator<Item = _>>
151        }
152    }
153}
154```
155
156## Positions where `#[auto_enum]` can be used.
157
158`#[auto_enum]` can be used in the following three places. However, since
159[stmt_expr_attributes] and [proc_macro_hygiene] are not stabilized, you need
160to use empty `#[auto_enum]` for functions except nightly.
161
162[stmt_expr_attributes]: https://github.com/rust-lang/rust/issues/15701
163[proc_macro_hygiene]: https://github.com/rust-lang/rust/issues/54727
164
165- functions
166
167  ```rust
168  use auto_enums::auto_enum;
169
170  #[auto_enum(Iterator)]
171  fn func(x: i32) -> impl Iterator<Item=i32> {
172      if x == 0 {
173          Some(0).into_iter()
174      } else {
175          0..x
176      }
177  }
178  ```
179
180- expressions
181
182  ```rust
183  use auto_enums::auto_enum;
184
185  #[auto_enum] // Nightly does not need an empty attribute to the function.
186  fn expr(x: i32) -> impl Iterator<Item=i32> {
187      #[auto_enum(Iterator)]
188      match x {
189          0 => Some(0).into_iter(),
190          _ => 0..x,
191      }
192  }
193  ```
194
195- let binding
196
197  ```rust
198  use auto_enums::auto_enum;
199
200  #[auto_enum] // Nightly does not need an empty attribute to the function.
201  fn let_binding(x: i32) -> impl Iterator<Item=i32> {
202      #[auto_enum(Iterator)]
203      let iter = match x {
204          0 => Some(0).into_iter(),
205          _ => 0..x,
206      };
207      iter
208  }
209  ```
210
211## Supported syntax
212
213- `if` and `match`
214
215  Wrap each branch with a variant.
216
217  ```rust
218  use auto_enums::auto_enum;
219
220  // if
221  #[auto_enum(Iterator)]
222  fn expr_if(x: i32) -> impl Iterator<Item=i32> {
223      if x == 0 {
224          Some(0).into_iter()
225      } else {
226          0..x
227      }
228  }
229
230  // match
231  #[auto_enum] // Nightly does not need an empty attribute to the function.
232  fn expr_match(x: i32) -> impl Iterator<Item=i32> {
233      #[auto_enum(Iterator)]
234      let iter = match x {
235          0 => Some(0).into_iter(),
236          _ => 0..x,
237      };
238      iter
239  }
240  ```
241
242- `loop`
243
244  Wrap each `break` with a variant. Nested loops and labeled `break` are
245  also supported.
246
247  ```rust
248  use auto_enums::auto_enum;
249
250  #[auto_enum(Iterator)]
251  fn expr_loop(mut x: i32) -> impl Iterator<Item = i32> {
252      loop {
253          if x < 0 {
254              break x..0;
255          } else if x % 5 == 0 {
256              break 0..=x;
257          }
258          x -= 1;
259      }
260  }
261  ```
262
263- `return` (in functions)
264
265  `#[auto_enum]` can parse the `return` in the scope.
266
267  This analysis is valid only when the return type is `impl Trait`.
268
269  ```rust
270  use auto_enums::auto_enum;
271
272  // return (in functions)
273  #[auto_enum(Iterator)]
274  fn func(x: i32) -> impl Iterator<Item=i32> {
275      if x == 0 {
276          return Some(0).into_iter();
277      }
278
279      if x > 0 {
280          0..x
281      } else {
282          x..=0
283      }
284  }
285  ```
286
287- `return` (in closures)
288
289  `#[auto_enum]` can parse the `return` in the scope.
290
291  This analysis is valid only when the following two conditions are satisfied.
292
293    - `#[auto_enum]` must be used directly for that closure (or the let binding of the closure).
294    - `?` operator not used in the scope.
295
296  ```rust
297  use auto_enums::auto_enum;
298
299  // return (in closures)
300  #[auto_enum] // Nightly does not need an empty attribute to the function.
301  fn closure() -> impl Iterator<Item=i32> {
302      #[auto_enum(Iterator)]
303      let f = |x| {
304          if x == 0 {
305              return Some(0).into_iter();
306          }
307
308          if x > 0 {
309              0..x
310          } else {
311              x..=0
312          }
313      };
314      f(1)
315  }
316  ```
317
318- `?` operator (in functions)
319
320  `#[auto_enum]` can parse the `?` operator in the scope.
321
322  This analysis is valid only when the return type is `Result<T, impl Trait>`.
323
324  ```rust
325  use auto_enums::auto_enum;
326  use std::fmt::{Debug, Display};
327
328  // `?` operator (in functions)
329  #[auto_enum(Debug, Display)]
330  fn func(x: i32) -> Result<i32, impl Debug + Display> {
331      if x == 0 {
332          Err("`x` is zero")?;
333      }
334
335      // The last branch of the function is not parsed.
336      if x < 0 {
337          Err(x)?
338      } else {
339          Ok(x + 1)
340      }
341  }
342  ```
343
344  `?` operator is expanded as follows:
345
346  ```rust
347  # enum Enum<A> { Variant(A) }
348  # fn dox<T, E>(expr: Result<T, E>) -> Result<T, Enum<E>> {
349  # Ok(
350  match expr {
351      Ok(val) => val,
352      Err(err) => return Err(Enum::Variant(err)),
353  }
354  # )
355  # }
356  ```
357
358- `?` operator (in closures)
359
360  `#[auto_enum]` can parse the `?` operator in the scope.
361
362  However, `#[auto_enum]` must be used directly for that closure
363  (or the let binding of the closure).
364
365  ```rust
366  use auto_enums::auto_enum;
367  use std::fmt::{Debug, Display};
368
369  // `?` operator (in closures)
370  #[auto_enum] // Nightly does not need an empty attribute to the function.
371  fn closure() -> Result<i32, impl Debug + Display> {
372      #[auto_enum(Debug, Display)]
373      let f = |x| {
374          if x == 0 {
375              Err("`x` is zero")?
376          }
377
378          // The last branch of the function is not interpreted as a branch.
379          if x < 0 {
380              Err(x)?
381          } else {
382              Ok(x + 1)
383          }
384      };
385      f(1)
386  }
387  ```
388
389- Block, unsafe block, method call, parentheses, and type ascription
390
391  The following expressions are recursively searched until an `if`, `match`,
392  `loop` or unsupported expression is found.
393
394  - blocks
395  - unsafe blocks
396  - method calls
397  - parentheses
398  - type ascriptions
399
400  ```rust
401  use auto_enums::auto_enum;
402
403  // block
404  #[auto_enum] // Nightly does not need an empty attribute to the function.
405  fn expr_block(x: i32) -> impl Iterator<Item=i32> {
406      #[auto_enum(Iterator)]
407      {
408          if x == 0 {
409              Some(0).into_iter()
410          } else {
411              0..x
412          }
413      }
414  }
415
416  // method call
417  #[auto_enum] // Nightly does not need an empty attribute to the function.
418  fn expr_method(x: i32) -> impl Iterator<Item=i32> {
419     #[auto_enum(Iterator)]
420      match x {
421          0 => Some(0).into_iter(),
422          _ => 0..x,
423      }.map(|y| y + 1)
424  }
425
426  // parentheses
427  # #[allow(unused_parens)]
428  #[auto_enum(Iterator)]
429  fn expr_parentheses(x: i32) -> impl Iterator<Item=i32> {
430      (if x == 0 { Some(0).into_iter() } else { 0..x })
431  }
432  ```
433
434## Expression that no value will be returned
435
436If the last expression of a branch is one of the following, it is
437interpreted that no value will be returned (variant assignment is skipped).
438
439- `panic!(..)`
440- `unreachable!(..)`
441- `return`
442- `break`
443- `continue`
444- `None?`
445- `Err(..)?`
446- Expression level marker (`marker!` macro).
447- An item definition.
448
449Also, if the branch contains `#[nested]`, it is interpreted as returning
450an anonymous enum generated by `#[auto_enum]`, not a value.
451
452```rust
453use auto_enums::auto_enum;
454
455#[auto_enum(Iterator)]
456fn foo(x: i32) -> impl Iterator<Item = i32> {
457    match x {
458        0 => 1..10,
459        1 => panic!(), // variant assignment is skipped
460        _ => vec![5, 10].into_iter(),
461    }
462}
463```
464
465You can also skip that branch explicitly by `#[never]` attribute.
466
467```rust
468use auto_enums::auto_enum;
469
470#[auto_enum(Iterator)]
471fn foo(x: i32) -> impl Iterator<Item = i32> {
472    match x {
473        0 => 1..10,
474        #[never]
475        1 => loop {
476            panic!()
477        },
478        _ => vec![5, 10].into_iter(),
479    }
480}
481```
482
483## Expression level marker (`marker!` macro)
484
485`#[auto_enum]` replaces `marker!` macros with variants.
486If values of two or more are specified by `marker!` macros, `#[auto_enum]`
487can be used for unsupported expressions and statements.
488
489```rust
490use auto_enums::auto_enum;
491
492#[auto_enum(Iterator)]
493fn foo(x: i32) -> impl Iterator<Item = i32> {
494    if x < 0 {
495        return x..=0;
496    }
497    marker!(1..10)
498}
499```
500
501The default name of the macro is `"marker"`, but you can change it by
502`marker` option.
503
504```rust
505use auto_enums::auto_enum;
506
507#[auto_enum(marker = bar, Iterator)]
508fn foo(x: i32) -> impl Iterator<Item = i32> {
509    if x < 0 {
510        return x..=0;
511    }
512    bar!(1..10)
513}
514```
515
516## Rust Nightly
517
518When using `#[auto_enum]` for expressions and statements, `#[auto_enum]` for
519function is unnecessary.
520
521```rust
522// Add this to your crate root:
523#![feature(proc_macro_hygiene, stmt_expr_attributes)]
524```
525
526```rust
527# #![feature(proc_macro_hygiene, stmt_expr_attributes)]
528use auto_enums::auto_enum;
529
530fn foo(x: i32) -> i32 {
531    #[auto_enum(Iterator)]
532    let iter = match x {
533        0 => 1..10,
534        _ => vec![5, 10].into_iter(),
535    };
536
537    iter.fold(0, |sum, x| sum + x)
538}
539```
540
541You can also return closures.
542
543```rust
544// Add this to your crate root:
545#![feature(fn_traits, unboxed_closures)]
546```
547
548```rust
549# #![feature(fn_traits, unboxed_closures)]
550use auto_enums::auto_enum;
551
552#[auto_enum(Fn)]
553fn foo(x: bool) -> impl Fn(i32) -> i32 {
554    if x {
555        |y| y + 1
556    } else {
557        |z| z - 1
558    }
559}
560```
561
562# `#[enum_derive]`
563
564`#[enum_derive]` implements the supported traits and passes unsupported
565traits to `#[derive]`.
566
567If you want to use traits that are not supported by `#[enum_derive]`, you
568can use another crate that provides [derives macros][proc-macro-derive], or
569you can define derives macros yourself ([derive_utils] probably can help it).
570
571Basic usage of `#[enum_derive]`
572
573```rust
574use auto_enums::enum_derive;
575
576// `#[enum_derive]` implements `Iterator`, and `#[derive]` implements `Clone`.
577#[enum_derive(Iterator, Clone)]
578enum Foo<A, B> {
579    A(A),
580    B(B),
581}
582```
583
584`#[enum_derive]` adds the dependency of the specified trait if it is not
585specified.
586
587```rust
588use auto_enums::enum_derive;
589
590// `#[enum_derive]` implements `Iterator` and `ExactSizeIterator`.
591#[enum_derive(ExactSizeIterator)]
592enum Foo<A, B> {
593    A(A),
594    B(B),
595}
596```
597
598[derive_utils]: https://github.com/taiki-e/derive_utils
599
600# Supported traits
601
602Some traits support is disabled by default.
603Note that some traits have aliases.
604
605*When using features that depend on unstable APIs, the `unstable` feature must be explicitly enabled*
606
607## The standard library (`std`, `core`)
608
609### `[std|core]::iter`
610
611- [`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/iter/iterator.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/iter/iterator.expanded.rs)
612- [`DoubleEndedIterator`](https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/iter/double_ended_iterator.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/iter/double_ended_iterator.expanded.rs)
613- [`ExactSizeIterator`](https://doc.rust-lang.org/std/iter/trait.ExactSizeIterator.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/iter/exact_size_iterator.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/iter/exact_size_iterator.expanded.rs)
614- [`FusedIterator`](https://doc.rust-lang.org/std/iter/trait.FusedIterator.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/iter/fused_iterator.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/iter/fused_iterator.expanded.rs)
615- [`Extend`](https://doc.rust-lang.org/std/iter/trait.Extend.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/iter/extend.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/iter/extend.expanded.rs)
616- [`TrustedLen`](https://doc.rust-lang.org/std/iter/trait.TrustedLen.html) *(requires `"trusted_len"` and `"unstable"` crate features)* - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/iter/trusted_len.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/iter/trusted_len.expanded.rs)
617
618*See also [iter-enum] crate.*
619
620### `[std|core]::future`
621
622- [`Future`](https://doc.rust-lang.org/std/future/trait.Future.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/future.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/future.expanded.rs)
623
624### `std::io` *(requires `"std"` crate feature)*
625
626- [`Read`](https://doc.rust-lang.org/std/io/trait.Read.html) (alias: `io::Read`) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/io/read.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/io/read.expanded.rs)
627- [`BufRead`](https://doc.rust-lang.org/std/io/trait.BufRead.html) (alias: `io::BufRead`) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/io/buf_read.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/io/buf_read.expanded.rs)
628- [`Write`](https://doc.rust-lang.org/std/io/trait.Write.html) (alias: `io::Write`) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/io/write.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/io/write.expanded.rs)
629- [`Seek`](https://doc.rust-lang.org/std/io/trait.Seek.html) (alias: `io::Seek`) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/io/seek.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/io/seek.expanded.rs)
630
631*See also [io-enum] crate.*
632
633### `[std|core]::ops`
634
635- [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) *(requires `"ops"` crate feature)*
636- [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html) *(requires `"ops"` crate feature)*
637- [`Index`](https://doc.rust-lang.org/std/ops/trait.Index.html) *(requires `"ops"` crate feature)*
638- [`IndexMut`](https://doc.rust-lang.org/std/ops/trait.IndexMut.html) *(requires `"ops"` crate feature)*
639- [`RangeBounds`](https://doc.rust-lang.org/std/ops/trait.RangeBounds.html) *(requires `"ops"` crate feature)*
640- [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html) *(requires `"fn_traits"` and `"unstable"` crate features)*
641- [`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html) *(requires `"fn_traits"` and `"unstable"` crate features)*
642- [`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) *(requires `"fn_traits"` and `"unstable"` crate features)*
643- [`Coroutine`](https://doc.rust-lang.org/nightly/std/ops/trait.Coroutine.html) *(requires `"coroutine_trait"` and `"unstable"` crate features)*
644
645### `[std|core]::convert`
646
647- [`AsRef`](https://doc.rust-lang.org/std/convert/trait.AsRef.html) *(requires `"convert"` crate feature)*
648- [`AsMut`](https://doc.rust-lang.org/std/convert/trait.AsMut.html) *(requires `"convert"` crate feature)*
649
650### `[std|core]::fmt`
651
652- [`Debug`](https://doc.rust-lang.org/std/fmt/trait.Debug.html) (alias: `fmt::Debug`) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/debug.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/debug.expanded.rs)
653- [`Display`](https://doc.rust-lang.org/std/fmt/trait.Display.html) (alias: `fmt::Display`)
654- [`fmt::Binary`](https://doc.rust-lang.org/std/fmt/trait.Binary.html) *(requires `"fmt"` crate feature)*
655- [`fmt::LowerExp`](https://doc.rust-lang.org/std/fmt/trait.LowerExp.html) *(requires `"fmt"` crate feature)*
656- [`fmt::LowerHex`](https://doc.rust-lang.org/std/fmt/trait.LowerHex.html) *(requires `"fmt"` crate feature)*
657- [`fmt::Octal`](https://doc.rust-lang.org/std/fmt/trait.Octal.html) *(requires `"fmt"` crate feature)*
658- [`fmt::Pointer`](https://doc.rust-lang.org/std/fmt/trait.Pointer.html) *(requires `"fmt"` crate feature)*
659- [`fmt::UpperExp`](https://doc.rust-lang.org/std/fmt/trait.UpperExp.html) *(requires `"fmt"` crate feature)*
660- [`fmt::UpperHex`](https://doc.rust-lang.org/std/fmt/trait.UpperHex.html) *(requires `"fmt"` crate feature)*
661- [`fmt::Write`](https://doc.rust-lang.org/std/fmt/trait.Write.html)
662
663### `std::error` *(requires `"std"` crate feature)*
664
665- [`Error`](https://doc.rust-lang.org/std/error/trait.Error.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/error.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/std/error.expanded.rs)
666
667## External libraries
668
669You can use support for external library traits by activating each crate feature.
670
671To use support for external library traits, you need to use the path starting with the feature name. For example:
672
673```rust
674# extern crate rayon_crate as rayon;
675use auto_enums::auto_enum;
676use rayon::prelude::*;
677
678#[auto_enum(rayon::ParallelIterator)] // Note that this is not `#[auto_enum(ParallelIterator)]`
679fn func(x: i32) -> impl ParallelIterator {
680    match x {
681        0 => (1..10).into_par_iter(),
682        _ => vec![5, 10].into_par_iter(),
683    }
684}
685```
686
687### [futures v0.3][futures03] *(requires `"futures03"` crate feature)*
688
689- [`futures03::Stream`](https://docs.rs/futures/0.3/futures/stream/trait.Stream.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/futures/stream.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/futures/stream.expanded.rs)
690- [`futures03::Sink`](https://docs.rs/futures/0.3/futures/sink/trait.Sink.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/futures/sink.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/futures/sink.expanded.rs)
691- [`futures03::AsyncRead`](https://docs.rs/futures/0.3/futures/io/trait.AsyncRead.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/futures/async_read.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/futures/async_read.expanded.rs)
692- [`futures03::AsyncWrite`](https://docs.rs/futures/0.3/futures/io/trait.AsyncWrite.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/futures/async_write.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/futures/async_write.expanded.rs)
693- [`futures03::AsyncSeek`](https://docs.rs/futures/0.3/futures/io/trait.AsyncSeek.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/futures/async_seek.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/futures/async_seek.expanded.rs)
694- [`futures03::AsyncBufRead`](https://docs.rs/futures/0.3/futures/io/trait.AsyncBufRead.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/futures/async_buf_read.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/futures/async_buf_read.expanded.rs)
695
696### [futures v0.1][futures01] *(requires `"futures01"` crate feature)*
697
698- [`futures01::Future`](https://docs.rs/futures/0.1/futures/future/trait.Future.html)
699- [`futures01::Stream`](https://docs.rs/futures/0.1/futures/stream/trait.Stream.html)
700- [`futures01::Sink`](https://docs.rs/futures/0.1/futures/sink/trait.Sink.html)
701
702### [rayon] *(requires `"rayon"` crate feature)*
703
704- [`rayon::ParallelIterator`](https://docs.rs/rayon/1/rayon/iter/trait.ParallelIterator.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/rayon/parallel_iterator.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/rayon/parallel_iterator.expanded.rs)
705- [`rayon::IndexedParallelIterator`](https://docs.rs/rayon/1/rayon/iter/trait.IndexedParallelIterator.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/rayon/indexed_parallel_iterator.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/rayon/indexed_parallel_iterator.expanded.rs)
706- [`rayon::ParallelExtend`](https://docs.rs/rayon/1/rayon/iter/trait.ParallelExtend.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/rayon/parallel_extend.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/rayon/parallel_extend.expanded.rs)
707
708### [serde] *(requires `"serde"` crate feature)*
709
710- [`serde::Serialize`](https://docs.rs/serde/1/serde/trait.Serialize.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/serde/serialize.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/serde/serialize.expanded.rs)
711
712### [tokio v1][tokio1] *(requires `"tokio1"` crate feature)*
713
714- [`tokio1::AsyncRead`](https://docs.rs/tokio/1/tokio/io/trait.AsyncRead.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/tokio/async_read.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/tokio/async_read.expanded.rs)
715- [`tokio1::AsyncWrite`](https://docs.rs/tokio/1/tokio/io/trait.AsyncWrite.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/tokio/async_write.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/tokio/async_write.expanded.rs)
716- [`tokio1::AsyncSeek`](https://docs.rs/tokio/1/tokio/io/trait.AsyncSeek.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/tokio/async_seek.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/tokio/async_seek.expanded.rs)
717- [`tokio1::AsyncBufRead`](https://docs.rs/tokio/1/tokio/io/trait.AsyncBufRead.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/tokio/async_buf_read.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/tokio/async_buf_read.expanded.rs)
718
719### [tokio v0.3][tokio03] *(requires `"tokio03"` crate feature)*
720
721- [`tokio03::AsyncRead`](https://docs.rs/tokio/0.3/tokio/io/trait.AsyncRead.html)
722- [`tokio03::AsyncWrite`](https://docs.rs/tokio/0.3/tokio/io/trait.AsyncWrite.html)
723- [`tokio03::AsyncSeek`](https://docs.rs/tokio/0.3/tokio/io/trait.AsyncSeek.html)
724- [`tokio03::AsyncBufRead`](https://docs.rs/tokio/0.3/tokio/io/trait.AsyncBufRead.html)
725
726### [tokio v0.2][tokio02] *(requires `"tokio02"` crate feature)*
727
728- [`tokio02::AsyncRead`](https://docs.rs/tokio/0.2/tokio/io/trait.AsyncRead.html)
729- [`tokio02::AsyncWrite`](https://docs.rs/tokio/0.2/tokio/io/trait.AsyncWrite.html)
730- [`tokio02::AsyncSeek`](https://docs.rs/tokio/0.2/tokio/io/trait.AsyncSeek.html)
731- [`tokio02::AsyncBufRead`](https://docs.rs/tokio/0.2/tokio/io/trait.AsyncBufRead.html)
732
733### [tokio v0.1][tokio01] *(requires `"tokio01"` crate feature)*
734
735- [`tokio01::AsyncRead`](https://docs.rs/tokio/0.1/tokio/io/trait.AsyncRead.html)
736- [`tokio01::AsyncWrite`](https://docs.rs/tokio/0.1/tokio/io/trait.AsyncWrite.html)
737
738### [http_body v1][http_body1] *(requires `"http_body1"` crate feature)*
739
740- [`http_body1::Body`](https://docs.rs/http-body/1/http_body/trait.Body.html) - [example](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/http_body/body.rs) | [generated code](https://github.com/taiki-e/auto_enums/blob/HEAD/tests/expand/external/http_body/body.expanded.rs)
741
742## Inherent methods
743
744These don't derive traits, but derive inherent methods instead.
745
746- `Transpose` *(requires `"transpose_methods"` crate feature)* - this derives the following conversion methods.
747
748  - `transpose` — convert from `enum<Option<T1>,..>` to `Option<enum<T1,..>>`
749
750  - `transpose` — convert from `enum<Result<T1, E1>,..>` to `Result<enum<T1,..>, enum<E1,..>>`
751
752  - `transpose_ok` — convert from `enum<Result<T1, E>,..>` to `Option<enum<T1,..>, E>`
753
754    Examples:
755
756    ```rust
757    use auto_enums::auto_enum;
758    use std::{fs::File, io, path::Path};
759
760    #[auto_enum(Transpose, Write)]
761    fn output_stream(file: Option<&Path>) -> io::Result<impl io::Write> {
762        match file {
763            Some(f) => File::create(f),
764            None => Ok(io::stdout()),
765        }.transpose_ok()
766    }
767    ```
768
769  - `transpose_err` — convert from `enum<Result<T, E1>,..>` to `Result<T, enum<E1,..>>`
770
771# Optional features
772
773- **`std`** *(enabled by default)*
774  - Enable to use `std` library's traits.
775- **`ops`**
776  - Enable to use `[std|core]::ops`'s `Deref`, `DerefMut`, `Index`, `IndexMut`, and `RangeBounds` traits.
777- **`convert`**
778  - Enable to use `[std|core]::convert`'s `AsRef` and `AsMut` traits.
779- **`fmt`**
780  - Enable to use `[std|core]::fmt`'s traits other than `Debug`, `Display` and `Write`.
781- **`transpose_methods`**
782  - Enable to use `transpose*` methods.
783- **`futures03`**
784  - Enable to use [futures v0.3][futures03] traits.
785- **`futures01`**
786  - Enable to use [futures v0.1][futures01] traits.
787- **`rayon`**
788  - Enable to use [rayon] traits.
789- **`serde`**
790  - Enable to use [serde] traits.
791- **`tokio1`**
792  - Enable to use [tokio v1][tokio1] traits.
793- **`tokio03`**
794  - Enable to use [tokio v0.3][tokio03] traits.
795- **`tokio02`**
796  - Enable to use [tokio v0.2][tokio02] traits.
797- **`tokio01`**
798  - Enable to use [tokio v0.1][tokio01] traits.
799- **`http_body1`**
800  - Enable to use [http_body v1][http_body1] traits.
801- **`coroutine_trait`**
802  - Enable to use `[std|core]::ops::Coroutine` trait.
803  - Note that this feature is unstable and may cause incompatible changes between patch versions.
804- **`fn_traits`**
805  - Enable to use `[std|core]::ops`'s `Fn`, `FnMut`, and `FnOnce` traits.
806  - Note that this feature is unstable and may cause incompatible changes between patch versions.
807- **`trusted_len`**
808  - Enable to use `[std|core]::iter::TrustedLen` trait.
809  - Note that this feature is unstable and may cause incompatible changes between patch versions.
810
811## `type_analysis` feature
812
813Analyze return type of function and `let` binding.
814
815*Note that this feature is still experimental.*
816
817Examples:
818
819```rust
820use auto_enums::auto_enum;
821
822#[auto_enum] // there is no need to specify std library's traits
823fn func1(x: i32) -> impl Iterator<Item = i32> {
824    match x {
825        0 => 1..10,
826        _ => vec![5, 10].into_iter(),
827    }
828}
829
830#[auto_enum]
831fn func2(x: i32) {
832    // Unlike `feature(impl_trait_in_bindings)`, this works on stable compilers.
833    #[auto_enum]
834    let iter: impl Iterator<Item = i32> = match x {
835        0 => Some(0).into_iter(),
836        _ => 0..x,
837    };
838}
839```
840
841Please be careful if you return another traits with the same name.
842
843# Known limitations
844
845- There needs to explicitly specify the trait to be implemented (`type_analysis` crate feature reduces this limitation).
846- There needs to be marker macros for unsupported expressions.
847
848## Related Projects
849
850- [derive_utils]: A procedural macro helper for easily writing [derives macros][proc-macro-derive] for enums.
851- [io-enum]: \#\[derive(Read, Write, Seek, BufRead)\] for enums.
852- [iter-enum]: \#\[derive(Iterator, DoubleEndedIterator, ExactSizeIterator, Extend)\] for enums.
853
854[derive_utils]: https://github.com/taiki-e/derive_utils
855[futures01]: https://docs.rs/futures/0.1
856[futures03]: https://docs.rs/futures/0.3
857[io-enum]: https://github.com/taiki-e/io-enum
858[iter-enum]: https://github.com/taiki-e/iter-enum
859[proc-macro-derive]: https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros
860[rayon]: https://docs.rs/rayon/1
861[rust-lang/rfcs#294]: https://github.com/rust-lang/rfcs/issues/294
862[rust-lang/rfcs#2414]: https://github.com/rust-lang/rfcs/issues/2414
863[serde]: https://docs.rs/serde/1
864[tokio01]: https://docs.rs/tokio/0.1
865[tokio02]: https://docs.rs/tokio/0.2
866[tokio03]: https://docs.rs/tokio/0.3
867[tokio1]: https://docs.rs/tokio/1
868[http_body1]: https://docs.rs/http-body/1
869*/
870
871#![doc(test(
872    no_crate_inject,
873    attr(
874        deny(warnings, rust_2018_idioms, single_use_lifetimes),
875        allow(dead_code, unused_variables)
876    )
877))]
878#![forbid(unsafe_code)]
879#![allow(clippy::doc_link_with_quotes)]
880
881#[cfg(all(feature = "coroutine_trait", not(feature = "unstable")))]
882compile_error!(
883    "The `coroutine_trait` feature requires the `unstable` feature as an explicit opt-in to unstable features"
884);
885
886#[cfg(all(feature = "fn_traits", not(feature = "unstable")))]
887compile_error!(
888    "The `fn_traits` feature requires the `unstable` feature as an explicit opt-in to unstable features"
889);
890
891#[cfg(all(feature = "trusted_len", not(feature = "unstable")))]
892compile_error!(
893    "The `trusted_len` feature requires the `unstable` feature as an explicit opt-in to unstable features"
894);
895
896#[cfg(doctest)]
897#[doc = include_str!("../README.md")]
898const _README: () = ();
899
900#[macro_use]
901mod error;
902
903mod auto_enum;
904mod derive;
905mod enum_derive;
906mod utils;
907
908use proc_macro::TokenStream;
909
910/// An attribute macro like a wrapper of `#[derive]`, implementing
911/// the supported traits and passing unsupported traits to `#[derive]`.
912///
913/// See crate level documentation for details.
914#[proc_macro_attribute]
915pub fn enum_derive(args: TokenStream, input: TokenStream) -> TokenStream {
916    crate::enum_derive::attribute(args.into(), input.into()).into()
917}
918
919/// An attribute macro for to allow multiple return types by automatically generated enum.
920///
921/// See crate level documentation for details.
922#[proc_macro_attribute]
923pub fn auto_enum(args: TokenStream, input: TokenStream) -> TokenStream {
924    crate::auto_enum::attribute(args.into(), input.into()).into()
925}