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:args.into(), input: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:args.into(), input:input.into()).into()
925}
926