auto_enums-0.8.7/.cargo_vcs_info.json0000644000000001360000000000100132270ustar { "git": { "sha1": "e41e4b2534ca29157707c1fe4fc06201e824a025" }, "path_in_vcs": "" }auto_enums-0.8.7/CHANGELOG.md000064400000000000000000000400751046102023000136360ustar 00000000000000# Changelog All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org). Releases may yanked if there is a security bug, a soundness bug, or a regression. ## [Unreleased] ## [0.8.7] - 2025-01-16 - Update `derive_utils` to 0.15. This uses `#[automatically_derived]` on generated impls to improve coverage support. ## [0.8.6] - 2024-08-23 - Disable `derive` feature of `syn` dependency. ## [0.8.5] - 2024-01-27 - Update `derive_utils` to 0.14. This fixes "overflow evaluating the requirement" error with `#[enum_derive]` in two situations. ## [0.8.4] - 2024-01-14 - Add support for `http_body1::Body`. ([#161](https://github.com/taiki-e/auto_enums/pull/161), thanks @nwtgck) ## [0.8.3] - 2023-10-21 - Update to [new coroutine API since nightly-2023-10-21](https://github.com/rust-lang/rust/pull/116958). This renames unstable `generator_trait` feature to `coroutine_trait`. The old cargo feature name is kept as a deprecated alias and will be removed in the next breaking release. ([daf9165](https://github.com/taiki-e/auto_enums/commit/daf91653b925d53cde57b598f0d884fe35a53c60)) - Recognize full path to std types/functions. ([28507ca](https://github.com/taiki-e/auto_enums/commit/28507ca34bdce58a371e9bc671495975f3a34d1d)) ## [0.8.2] - 2023-08-10 - Update `syn` to 2. ([#158](https://github.com/taiki-e/auto_enums/pull/158), thanks @cuviper) ## [0.8.1] - 2023-06-29 - Increase the minimum supported Rust version from Rust 1.31 to Rust 1.56. - Update minimal version of `proc-macro2` to 1.0.60. ## [0.8.0] - 2022-12-10 - Remove `futures` feature. Use `futures03` feature instead. ([#124](https://github.com/taiki-e/auto_enums/pull/124)) - Merge `auto_enums_core` and `auto_enums_derive` crates into main `auto_enums` crate. ([#123](https://github.com/taiki-e/auto_enums/pull/123)) - Forbid custom `Unpin`/`Drop` impl if trait has `Pin<&mut self>` receiver. See [#135](https://github.com/taiki-e/auto_enums/pull/135) for more. - Update `derive_utils` to 0.12. ([#135](https://github.com/taiki-e/auto_enums/pull/135)) ## [0.7.12] - 2021-01-05 - Exclude unneeded files from crates.io. ## [0.7.11] - 2020-12-23 - [Add support for `tokio1::{AsyncRead, AsyncWrite, AsyncSeek, AsyncBufRead}`.](https://github.com/taiki-e/auto_enums/pull/122) ## [0.7.10] - 2020-11-15 - Documentation improvements. ## [0.7.9] - 2020-11-06 - Update `derive_utils` to 0.11. ## [0.7.8] - 2020-10-16 - [Add support for `tokio03::{AsyncRead, AsyncWrite, AsyncSeek, AsyncBufRead}`.](https://github.com/taiki-e/auto_enums/pull/114) ## [0.7.7] - 2020-09-21 - [Fix panic when multiple errors occur.](https://github.com/taiki-e/auto_enums/pull/111) - Diagnostic improvements. ## [0.7.6] - 2020-09-18 - [`type_analysis` feature can now support impl trait in bindings.](https://github.com/taiki-e/auto_enums/pull/108) ```rust #[auto_enum] fn foo(x: i32) { // Unlike `feature(impl_trait_in_bindings)`, this works on stable compilers. #[auto_enum] let iter: impl Iterator = match x { 0 => Some(0).into_iter(), _ => 0..x, }; } ``` ## [0.7.5] - 2020-06-03 - Updated `derive_utils` to 0.10. ## [0.7.4] - 2020-05-07 - [Fixed an issue that `#[auto_enum]` on non-statement expression does not work without unstable features.](https://github.com/taiki-e/auto_enums/pull/97) ## [0.7.3] - 2020-04-19 - [Added support for `tokio02::{AsyncRead, AsyncWrite, AsyncSeek, AsyncBufRead}`.](https://github.com/taiki-e/auto_enums/pull/92) - [Added support for `tokio01::{AsyncRead, AsyncWrite}`.](https://github.com/taiki-e/auto_enums/pull/92) - [Added `futures03` feature. This is an alias of `futures` feature.](https://github.com/taiki-e/auto_enums/pull/92) ## [0.7.2] - 2020-04-13 - [Fix unused braces warnings.](https://github.com/taiki-e/auto_enums/pull/88) - Update to support latest generator. ## [0.7.1] - 2019-11-16 - Updated to support `futures` 0.3.0. (futures feature is no longer unstable) ## [0.7.0] - 2019-10-20 - [Support `#[nested]` for nested if expressions.](https://github.com/taiki-e/auto_enums/pull/67) - Fixed bugs of `"type_analysis"` feature. - [Removed unstable `"exact_size_is_empty"`, `"read_initializer"`, and `"try_trait"` crate features.](https://github.com/taiki-e/auto_enums/pull/69) ## [0.6.4] - 2019-09-28 - Updated to support `futures-preview` 0.3.0-alpha.19. ## [0.6.3] - 2019-09-20 - [Removed usage of mutable global state from `#[auto_enum]` for forward compatibility.](https://github.com/taiki-e/auto_enums/pull/60) See also [rust-lang/rust#63831](https://github.com/rust-lang/rust/pull/63831). ## [0.6.2] - 2019-09-08 - Fixed links to generated code. ## [0.6.1] - 2019-09-08 - Documentation improvements. ## [0.6.0] - 2019-09-07 - [Added `"unstable"` crate feature to separate unstable features from stable features.](https://github.com/taiki-e/auto_enums/pull/56) When using features that depend on unstable APIs, the `"unstable"` feature must be explicitly enabled. - Improved compile time. - Renamed `#[rec]` to `#[nested]`. - [Removed `marker(name)` option in favor of `marker = name`.](https://github.com/taiki-e/auto_enums/pull/55) - [Removed `never` option in argument position in favor of `#[enum_derive]` attribute.](https://github.com/taiki-e/auto_enums/pull/48) - [Removed `"proc_macro"` crate feature.](https://github.com/taiki-e/auto_enums/pull/54) - Added `"ops"` crate feature, and made `[std|core]::ops`'s `Deref`, `DerefMut`, `Index`, `IndexMut`, and `RangeBounds` traits optional. - Added `"convert"` crate feature, and made `[std|core]::convert`'s `AsRef` and `AsMut` traits optional. - Added `"generator_trait"` crate feature, and made `[std|core]::ops::Generator` traits optional. *(nightly-only)* - Added `"fn_traits"` crate feature, and made `Fn`, `FnMut`, and `FnOnce` traits optional. *(nightly-only)* - Added `"trusted_len"` crate feature, and made `[std|core]::iter::TrustedLen` traits optional. *(nightly-only)* - Diagnostic improvements. (There are no changes since the 0.6.0-alpha.3 release.) ## [0.6.0-alpha.3] - 2019-09-06 - [Added `"unstable"` crate feature to separate unstable features from stable features.](https://github.com/taiki-e/auto_enums/pull/56) When using features that depend on unstable APIs, the `"unstable"` feature must be explicitly enabled. ## [0.6.0-alpha.2] - 2019-08-30 - [Removed `marker(name)` option in favor of `marker = name`.](https://github.com/taiki-e/auto_enums/pull/55) - [Removed `"proc_macro"` crate feature.](https://github.com/taiki-e/auto_enums/pull/54) ## [0.6.0-alpha.1] - 2019-08-24 - Renamed `#[rec]` to `#[nested]`. - [Removed `never` option in argument position in favor of `#[enum_derive]` attribute.](https://github.com/taiki-e/auto_enums/pull/48) - Improved compile time. - Added `"ops"` crate feature, and made `[std|core]::ops`'s `Deref`, `DerefMut`, `Index`, `IndexMut`, and `RangeBounds` traits optional. - Added `"convert"` crate feature, and made `[std|core]::convert`'s `AsRef` and `AsMut` traits optional. - Added `"generator_trait"` crate feature, and made `[std|core]::ops::Generator` traits optional. *(nightly-only)* - Added `"fn_traits"` crate feature, and made `Fn`, `FnMut`, and `FnOnce` traits optional. *(nightly-only)* - Added `"trusted_len"` crate feature, and made `[std|core]::iter::TrustedLen` traits optional. *(nightly-only)* - Diagnostic improvements. ## [0.5.10] - 2019-08-15 - Updated `proc-macro2`, `syn`, and `quote` to 1.0. - Updated `derive_utils` to 0.9. This improves the error message. - Added some generated code examples. ## [0.5.9] - 2019-07-07 - Updated to support `futures-preview` 0.3.0-alpha.17. - Added some generated code examples. ## [0.5.8] - 2019-05-22 - Added support for `futures::io::{AsyncSeek, AsyncBufRead}`. ## [0.5.7] - 2019-05-12 - Updated to new nightly. `iovec` stabilized. `#[enum_derive]` automatically detects the rustc version and supports `Read::read_vectored` and `Write::write_vectored` as the part of `Read` and `Write`. - Supported for latest `futures` 0.3.0-alpha.16. ## [0.5.6] - 2019-04-16 - Updated to new nightly. `futures_api` stabilized. ## [0.5.5] - 2019-03-29 - Fixed trait support in `"type_analysis"` feature. ## [0.5.4] - 2019-03-14 - Fixed the problem that `"failed to resolve: use of undeclared type or module"` (E0433) error is shown when one or more compilation errors occur when multiple `#[auto_enum]` attributes are used. - Improved the error message of `#[enum_derive]` attribute. - Updated minimum `derive_utils` version to 0.7.0. This improves the error message. ## [0.5.3] - 2019-03-13 - Greatly improved the error message of `#[auto_enum]` attribute. ## [0.5.2] - 2019-03-10 - Added some generated code examples. - Added `"iovec"` crate feature. This supports the unstable `iovec` feature ([rust-lang/rust#58452](https://github.com/rust-lang/rust/issues/58452)). - Updated minimum `syn` version to 0.15.29. This fixes some warnings. ## [0.5.1] - 2019-03-03 - Fixed examples and some sentence in README.md. ## [0.5.0] - 2019-03-03 - Transition to Rust 2018. With this change, the minimum required version will go up to Rust 1.31. - Reduced the feature of `"std"` crate feature. The current `"std"` crate feature only determines whether to enable `std` library's traits (e.g., `std::io::Read`) support. `"std"` crate feature is enabled by default, but you can reduce compile time by disabling this feature. - Fixed problem where "macro attributes must be placed before `#[derive]`" error occurred when `#[enum_derive]` attribute was used with other attributes. - No longer need `#[macro_use] extern crate auto_enums;`. You can use `#[auto_enum]` attribute by `use auto_enums::auto_enum;`. - Removed `"unstable"` crate feature. ## [0.4.1] - 2019-02-21 - Updated to new nightly. - Added some generated code examples. - Updated minimum `derive_utils` version to 0.6.3. - Updated minimum `syn` version to 0.15.22. - Updated minimum `smallvec` version to 0.6.9. ## [0.4.0] - 2019-01-30 - Added support for `?` operator in functions and closures. - Added support for `[core|std]::ops::Generator`. ## [0.3.8] - 2019-01-26 - Updated minimum `derive_utils` version to 0.6.1. - Updated minimum `smallvec` version to 0.6.8. ## [0.3.7] - 2019-01-26 - Fixed bug of closure support. ## [0.3.6] - 2019-01-19 - Parentheses and type ascription can now be searched recursively. ## [0.3.5] - 2019-01-09 - Improved performance of `#[auto_enum]` attribute. - Updated minimum `derive_utils` version to 0.6.0. ## [0.3.4] - 2019-01-06 - Added support for `futures::{AsyncRead, AsyncWrite}`. ## [0.3.3] - 2019-01-04 - Updated minimum `derive_utils` version to 0.5.4. ## [0.3.2] - 2018-12-27 - Improved error messages. - Updated minimum `derive_utils` version to 0.5.3. ## [0.3.1] - 2018-12-26 - Updated minimum `derive_utils` version to 0.5.1. This includes support to stable Pin API. ## [0.3.0] - 2018-12-24 - Added support for `break` in loop. This includes support for nested loops and labeled `break`. - Changed `#[enum_derive(Error)]` implementation. [The code generated by the new implementation](https://github.com/taiki-e/auto_enums/tree/v0.3.0/docs/supported_traits/std/error.md). - Removed `"error_cause"` crate feature. - Updated minimum `derive_utils` version to 0.5.0. ## [0.2.1] - 2018-12-22 - Updated minimum `derive_utils` version to 0.4.0. ## [0.2.0] - 2018-12-20 - Added support for `return` in function and closure. - Added `"fmt"` crate feature, and made `[std|core]::fmt`'s traits other than `Debug`, `Display` and `Write` optional. ## [0.1.3] - 2018-12-15 - Changed `#[enum_derive(Error)]` implementation. In Rust 1.33, `Error::cause` is deprecated. In the new implementation, `Error::cause` is optional for Rust 1.33 and later. In versions less than 1.33, `Error::cause` is always implemented. ## [0.1.2] - 2018-12-15 - Moved features of derive/utils to [derive_utils](https://github.com/taiki-e/derive_utils). - Aligned version number of `auto_enumerate` and `auto_enums`. ## 0.1.1 - 2018-12-13 - Renamed from `auto_enumerate` to `auto_enums`. ## 0.1.0 - 2018-12-09 Initial release [Unreleased]: https://github.com/taiki-e/auto_enums/compare/v0.8.7...HEAD [0.8.7]: https://github.com/taiki-e/auto_enums/compare/v0.8.6...v0.8.7 [0.8.6]: https://github.com/taiki-e/auto_enums/compare/v0.8.5...v0.8.6 [0.8.5]: https://github.com/taiki-e/auto_enums/compare/v0.8.4...v0.8.5 [0.8.4]: https://github.com/taiki-e/auto_enums/compare/v0.8.3...v0.8.4 [0.8.3]: https://github.com/taiki-e/auto_enums/compare/v0.8.2...v0.8.3 [0.8.2]: https://github.com/taiki-e/auto_enums/compare/v0.8.1...v0.8.2 [0.8.1]: https://github.com/taiki-e/auto_enums/compare/v0.8.0...v0.8.1 [0.8.0]: https://github.com/taiki-e/auto_enums/compare/v0.7.12...v0.8.0 [0.7.12]: https://github.com/taiki-e/auto_enums/compare/v0.7.11...v0.7.12 [0.7.11]: https://github.com/taiki-e/auto_enums/compare/v0.7.10...v0.7.11 [0.7.10]: https://github.com/taiki-e/auto_enums/compare/v0.7.9...v0.7.10 [0.7.9]: https://github.com/taiki-e/auto_enums/compare/v0.7.8...v0.7.9 [0.7.8]: https://github.com/taiki-e/auto_enums/compare/v0.7.7...v0.7.8 [0.7.7]: https://github.com/taiki-e/auto_enums/compare/v0.7.6...v0.7.7 [0.7.6]: https://github.com/taiki-e/auto_enums/compare/v0.7.5...v0.7.6 [0.7.5]: https://github.com/taiki-e/auto_enums/compare/v0.7.4...v0.7.5 [0.7.4]: https://github.com/taiki-e/auto_enums/compare/v0.7.3...v0.7.4 [0.7.3]: https://github.com/taiki-e/auto_enums/compare/v0.7.2...v0.7.3 [0.7.2]: https://github.com/taiki-e/auto_enums/compare/v0.7.1...v0.7.2 [0.7.1]: https://github.com/taiki-e/auto_enums/compare/v0.7.0...v0.7.1 [0.7.0]: https://github.com/taiki-e/auto_enums/compare/v0.6.4...v0.7.0 [0.6.4]: https://github.com/taiki-e/auto_enums/compare/v0.6.3...v0.6.4 [0.6.3]: https://github.com/taiki-e/auto_enums/compare/v0.6.2...v0.6.3 [0.6.2]: https://github.com/taiki-e/auto_enums/compare/v0.6.1...v0.6.2 [0.6.1]: https://github.com/taiki-e/auto_enums/compare/v0.6.0...v0.6.1 [0.6.0]: https://github.com/taiki-e/auto_enums/compare/v0.6.0-alpha.3...v0.6.0 [0.6.0-alpha.3]: https://github.com/taiki-e/auto_enums/compare/v0.6.0-alpha.2...v0.6.0-alpha.3 [0.6.0-alpha.2]: https://github.com/taiki-e/auto_enums/compare/v0.6.0-alpha.1...v0.6.0-alpha.2 [0.6.0-alpha.1]: https://github.com/taiki-e/auto_enums/compare/v0.5.10...v0.6.0-alpha.1 [0.5.10]: https://github.com/taiki-e/auto_enums/compare/v0.5.9...v0.5.10 [0.5.9]: https://github.com/taiki-e/auto_enums/compare/v0.5.8...v0.5.9 [0.5.8]: https://github.com/taiki-e/auto_enums/compare/v0.5.7...v0.5.8 [0.5.7]: https://github.com/taiki-e/auto_enums/compare/v0.5.6...v0.5.7 [0.5.6]: https://github.com/taiki-e/auto_enums/compare/v0.5.5...v0.5.6 [0.5.5]: https://github.com/taiki-e/auto_enums/compare/v0.5.4...v0.5.5 [0.5.4]: https://github.com/taiki-e/auto_enums/compare/v0.5.3...v0.5.4 [0.5.3]: https://github.com/taiki-e/auto_enums/compare/v0.5.2...v0.5.3 [0.5.2]: https://github.com/taiki-e/auto_enums/compare/v0.5.1...v0.5.2 [0.5.1]: https://github.com/taiki-e/auto_enums/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/taiki-e/auto_enums/compare/v0.4.1...v0.5.0 [0.4.1]: https://github.com/taiki-e/auto_enums/compare/v0.4.0...v0.4.1 [0.4.0]: https://github.com/taiki-e/auto_enums/compare/v0.3.8...v0.4.0 [0.3.8]: https://github.com/taiki-e/auto_enums/compare/v0.3.7...v0.3.8 [0.3.7]: https://github.com/taiki-e/auto_enums/compare/v0.3.6...v0.3.7 [0.3.6]: https://github.com/taiki-e/auto_enums/compare/v0.3.5...v0.3.6 [0.3.5]: https://github.com/taiki-e/auto_enums/compare/v0.3.4...v0.3.5 [0.3.4]: https://github.com/taiki-e/auto_enums/compare/v0.3.3...v0.3.4 [0.3.3]: https://github.com/taiki-e/auto_enums/compare/v0.3.2...v0.3.3 [0.3.2]: https://github.com/taiki-e/auto_enums/compare/v0.3.1...v0.3.2 [0.3.1]: https://github.com/taiki-e/auto_enums/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/taiki-e/auto_enums/compare/v0.2.1...v0.3.0 [0.2.1]: https://github.com/taiki-e/auto_enums/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/taiki-e/auto_enums/compare/v0.1.3...v0.2.0 [0.1.3]: https://github.com/taiki-e/auto_enums/compare/v0.1.2...v0.1.3 [0.1.2]: https://github.com/taiki-e/auto_enums/releases/tag/v0.1.2 auto_enums-0.8.7/Cargo.lock0000644000000321270000000000100112070ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "addr2line" version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] name = "adler2" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "auto_enums" version = "0.8.7" dependencies = [ "derive_utils", "futures", "futures-util", "http-body", "proc-macro2", "quote", "rayon", "rustversion", "serde", "syn", "tokio 0.1.22", "tokio 0.2.25", "tokio 0.3.7", "tokio 1.43.0", ] [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", "windows-targets", ] [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" dependencies = [ "byteorder", "iovec", ] [[package]] name = "bytes" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "bytes" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "crossbeam-deque" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "derive_utils" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccfae181bab5ab6c5478b2ccb69e4c68a02f8c3ec72f6616bfec9dbc599d2ee0" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "either" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "futures" version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-io" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-sink" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-io", "futures-sink", "futures-task", "memchr", "pin-project-lite 0.2.16", "pin-utils", "slab", ] [[package]] name = "gimli" version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "http" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes 1.9.0", "fnv", "itoa", ] [[package]] name = "http-body" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes 1.9.0", "http", ] [[package]] name = "iovec" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" dependencies = [ "libc", ] [[package]] name = "itoa" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "libc" version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "log" version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ "adler2", ] [[package]] name = "object" version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "pin-project-lite" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] name = "rayon" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", ] [[package]] name = "rayon-core" version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustversion" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "serde" version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "slab" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "syn" version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "tokio" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" dependencies = [ "bytes 0.4.12", "futures", "tokio-io", ] [[package]] name = "tokio" version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" dependencies = [ "bytes 0.5.6", "pin-project-lite 0.1.12", ] [[package]] name = "tokio" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46409491c9375a693ce7032101970a54f8a2010efb77e13f70788f0d84489e39" dependencies = [ "autocfg", "pin-project-lite 0.2.16", ] [[package]] name = "tokio" version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "pin-project-lite 0.2.16", ] [[package]] name = "tokio-io" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ "bytes 0.4.12", "futures", "log", ] [[package]] name = "unicode-ident" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" auto_enums-0.8.7/Cargo.toml0000644000000120540000000000100112270ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.56" name = "auto_enums" version = "0.8.7" build = false exclude = [ "/.*", "/tools", "/DEVELOPMENT.md", ] autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = """ A library for to allow multiple return types by automatically generated enum. """ readme = "README.md" keywords = [ "enum", "macros", "derive", "attribute", ] categories = [ "no-std", "no-std::no-alloc", "rust-patterns", ] license = "Apache-2.0 OR MIT" repository = "https://github.com/taiki-e/auto_enums" [package.metadata.docs.rs] all-features = true targets = ["x86_64-unknown-linux-gnu"] [lib] name = "auto_enums" path = "src/lib.rs" proc-macro = true [[test]] name = "auto_enum" path = "tests/auto_enum.rs" [[test]] name = "compiletest" path = "tests/compiletest.rs" [[test]] name = "enum_derive" path = "tests/enum_derive.rs" [[test]] name = "expandtest" path = "tests/expandtest.rs" [[test]] name = "type_analysis" path = "tests/type_analysis.rs" [dependencies.derive_utils] version = "0.15" [dependencies.proc-macro2] version = "1.0.60" [dependencies.quote] version = "1.0.25" [dependencies.syn] version = "2.0.1" features = [ "parsing", "printing", "clone-impls", "proc-macro", "full", "visit-mut", ] default-features = false [dev-dependencies.futures01_crate] version = "0.1" package = "futures" [dev-dependencies.futures03_crate] version = "0.3" features = [ "std", "io", "sink", ] default-features = false package = "futures-util" [dev-dependencies.http_body1_crate] version = "1" default-features = false package = "http-body" [dev-dependencies.rayon_crate] version = "1" package = "rayon" [dev-dependencies.rustversion] version = "1" [dev-dependencies.serde_crate] version = "1" package = "serde" [dev-dependencies.tokio01_crate] version = "0.1" features = ["io"] default-features = false package = "tokio" [dev-dependencies.tokio02_crate] version = "0.2" default-features = false package = "tokio" [dev-dependencies.tokio03_crate] version = "0.3" default-features = false package = "tokio" [dev-dependencies.tokio1_crate] version = "1" default-features = false package = "tokio" [features] convert = [] coroutine_trait = [] default = ["std"] fmt = [] fn_traits = [] futures01 = [] futures03 = [] generator_trait = ["coroutine_trait"] http_body1 = [] ops = [] rayon = [] serde = [] std = [] tokio01 = [] tokio02 = [] tokio03 = [] tokio1 = [] transpose_methods = [] trusted_len = [] type_analysis = [] unstable = [] [lints.clippy] all = "warn" as_ptr_cast_mut = "warn" as_underscore = "warn" default_union_representation = "warn" inline_asm_x86_att_syntax = "warn" pedantic = "warn" trailing_empty_array = "warn" transmute_undefined_repr = "warn" undocumented_unsafe_blocks = "warn" unused_trait_names = "warn" [lints.clippy.bool_assert_comparison] level = "allow" priority = 1 [lints.clippy.borrow_as_ptr] level = "allow" priority = 1 [lints.clippy.cast_lossless] level = "allow" priority = 1 [lints.clippy.declare_interior_mutable_const] level = "allow" priority = 1 [lints.clippy.doc_markdown] level = "allow" priority = 1 [lints.clippy.float_cmp] level = "allow" priority = 1 [lints.clippy.incompatible_msrv] level = "allow" priority = 1 [lints.clippy.lint_groups_priority] level = "allow" priority = 1 [lints.clippy.manual_assert] level = "allow" priority = 1 [lints.clippy.manual_range_contains] level = "allow" priority = 1 [lints.clippy.missing_errors_doc] level = "allow" priority = 1 [lints.clippy.module_name_repetitions] level = "allow" priority = 1 [lints.clippy.naive_bytecount] level = "allow" priority = 1 [lints.clippy.nonminimal_bool] level = "allow" priority = 1 [lints.clippy.range_plus_one] level = "allow" priority = 1 [lints.clippy.similar_names] level = "allow" priority = 1 [lints.clippy.single_match] level = "allow" priority = 1 [lints.clippy.single_match_else] level = "allow" priority = 1 [lints.clippy.struct_excessive_bools] level = "allow" priority = 1 [lints.clippy.struct_field_names] level = "allow" priority = 1 [lints.clippy.too_many_arguments] level = "allow" priority = 1 [lints.clippy.too_many_lines] level = "allow" priority = 1 [lints.clippy.type_complexity] level = "allow" priority = 1 [lints.clippy.unreadable_literal] level = "allow" priority = 1 [lints.rust] deprecated_safe = "warn" improper_ctypes = "warn" improper_ctypes_definitions = "warn" non_ascii_idents = "warn" rust_2018_idioms = "warn" single_use_lifetimes = "warn" unnameable_types = "warn" unreachable_pub = "warn" [lints.rust.unexpected_cfgs] level = "warn" priority = 0 check-cfg = [] auto_enums-0.8.7/Cargo.toml.orig000064400000000000000000000150561046102023000147150ustar 00000000000000[package] name = "auto_enums" version = "0.8.7" #publish:version edition = "2021" rust-version = "1.56" # For syn license = "Apache-2.0 OR MIT" repository = "https://github.com/taiki-e/auto_enums" keywords = ["enum", "macros", "derive", "attribute"] categories = ["no-std", "no-std::no-alloc", "rust-patterns"] exclude = ["/.*", "/tools", "/DEVELOPMENT.md"] description = """ A library for to allow multiple return types by automatically generated enum. """ [package.metadata.docs.rs] all-features = true targets = ["x86_64-unknown-linux-gnu"] [lib] proc-macro = true [features] # Default features. default = ["std"] # Analyze return type of function and `let` binding. type_analysis = [] # Enable to use `transpose*` methods. transpose_methods = [] # ------------------------------------------------------------------------------ # [std|core] libraries # Enable to use `std` library's traits. std = [] # Enable to use `[std|core]::ops`'s `Deref`, `DerefMut`, `Index`, `IndexMut`, and `RangeBounds` traits. ops = [] # Enable to use `[std|core]::convert`'s `AsRef` and `AsMut` traits. convert = [] # Enable to use `[std|core]::fmt`'s traits other than `Debug`, `Display` and `Write` fmt = [] # ------------------------------------------------------------------------------ # Using external libraries # https://docs.rs/futures/0.3 futures03 = [] # https://docs.rs/futures/0.1 futures01 = [] # https://docs.rs/rayon/1 rayon = [] # https://docs.rs/serde/1 serde = [] # https://docs.rs/tokio/1 tokio1 = [] # https://docs.rs/tokio/0.3 tokio03 = [] # https://docs.rs/tokio/0.2 tokio02 = [] # https://docs.rs/tokio/0.1 tokio01 = [] # https://docs.rs/http-body/1 http_body1 = [] # ------------------------------------------------------------------------------ # Unstable features # These features are outside of the normal semver guarantees and require the # `unstable` feature as an explicit opt-in to unstable API. unstable = [] # Enable unstable features of [std|core] libraries # Enable to use `[std|core]::ops::Coroutine` trait. coroutine_trait = [] generator_trait = ["coroutine_trait"] # alias for coroutine_trait; TODO: remove in the next breaking release # Enable to use `[std|core]::ops`'s `Fn`, `FnMut`, and `FnOnce` traits. fn_traits = [] # Enable to use `[std|core]::iter::TrustedLen` trait. trusted_len = [] # Note: futures, tokio, rayon, serde, and http-body are public dependencies. [dependencies] derive_utils = "0.15" proc-macro2 = "1.0.60" quote = "1.0.25" syn = { version = "2.0.1", default-features = false, features = ["parsing", "printing", "clone-impls", "proc-macro", "full", "visit-mut"] } [dev-dependencies] macrotest = { git = "https://github.com/taiki-e/macrotest.git", branch = "dev" } # adjust overwrite behavior + no cargo-expand rustversion = "1" trybuild = { git = "https://github.com/taiki-e/trybuild.git", branch = "dev" } # adjust overwrite behavior # for `#[enum_derive]` futures03_crate = { package = "futures-util", version = "0.3", default-features = false, features = ["std", "io", "sink"] } futures01_crate = { package = "futures", version = "0.1" } tokio1_crate = { package = "tokio", version = "1", default-features = false } tokio03_crate = { package = "tokio", version = "0.3", default-features = false } tokio02_crate = { package = "tokio", version = "0.2", default-features = false } tokio01_crate = { package = "tokio", version = "0.1", default-features = false, features = ["io"] } rayon_crate = { package = "rayon", version = "1" } serde_crate = { package = "serde", version = "1" } http_body1_crate = { package = "http-body", version = "1", default-features = false } [lints] workspace = true [workspace] resolver = "2" members = ["bench"] # This table is shared by projects under github.com/taiki-e. # It is not intended for manual editing. [workspace.lints.rust] deprecated_safe = "warn" improper_ctypes = "warn" improper_ctypes_definitions = "warn" non_ascii_idents = "warn" rust_2018_idioms = "warn" single_use_lifetimes = "warn" unexpected_cfgs = { level = "warn", check-cfg = [ ] } unnameable_types = "warn" unreachable_pub = "warn" # unsafe_op_in_unsafe_fn = "warn" # Set at crate-level instead since https://github.com/rust-lang/rust/pull/100081 is not available on MSRV [workspace.lints.clippy] all = "warn" # Downgrade deny-by-default lints pedantic = "warn" as_ptr_cast_mut = "warn" as_underscore = "warn" default_union_representation = "warn" inline_asm_x86_att_syntax = "warn" trailing_empty_array = "warn" transmute_undefined_repr = "warn" undocumented_unsafe_blocks = "warn" unused_trait_names = "warn" # Suppress buggy or noisy clippy lints bool_assert_comparison = { level = "allow", priority = 1 } borrow_as_ptr = { level = "allow", priority = 1 } # https://github.com/rust-lang/rust-clippy/issues/8286 cast_lossless = { level = "allow", priority = 1 } # https://godbolt.org/z/Pv6vbGG6E declare_interior_mutable_const = { level = "allow", priority = 1 } # https://github.com/rust-lang/rust-clippy/issues/7665 doc_markdown = { level = "allow", priority = 1 } float_cmp = { level = "allow", priority = 1 } # https://github.com/rust-lang/rust-clippy/issues/7725 incompatible_msrv = { level = "allow", priority = 1 } # buggy: doesn't consider cfg, https://github.com/rust-lang/rust-clippy/issues/12280, https://github.com/rust-lang/rust-clippy/issues/12257#issuecomment-2093667187 lint_groups_priority = { level = "allow", priority = 1 } # https://github.com/rust-lang/rust-clippy/issues/12920 manual_assert = { level = "allow", priority = 1 } manual_range_contains = { level = "allow", priority = 1 } # https://github.com/rust-lang/rust-clippy/issues/6455#issuecomment-1225966395 missing_errors_doc = { level = "allow", priority = 1 } module_name_repetitions = { level = "allow", priority = 1 } # buggy: https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+is%3Aopen+module_name_repetitions naive_bytecount = { level = "allow", priority = 1 } nonminimal_bool = { level = "allow", priority = 1 } # buggy: https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+is%3Aopen+nonminimal_bool range_plus_one = { level = "allow", priority = 1 } # buggy: https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+is%3Aopen+range_plus_one similar_names = { level = "allow", priority = 1 } single_match = { level = "allow", priority = 1 } single_match_else = { level = "allow", priority = 1 } struct_excessive_bools = { level = "allow", priority = 1 } struct_field_names = { level = "allow", priority = 1 } too_many_arguments = { level = "allow", priority = 1 } too_many_lines = { level = "allow", priority = 1 } type_complexity = { level = "allow", priority = 1 } unreadable_literal = { level = "allow", priority = 1 } auto_enums-0.8.7/LICENSE-APACHE000064400000000000000000000236761046102023000137610ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS auto_enums-0.8.7/LICENSE-MIT000064400000000000000000000017771046102023000134670ustar 00000000000000Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. auto_enums-0.8.7/README.md000064400000000000000000000160201046102023000132750ustar 00000000000000# auto_enums [![crates.io](https://img.shields.io/crates/v/auto_enums?style=flat-square&logo=rust)](https://crates.io/crates/auto_enums) [![docs.rs](https://img.shields.io/badge/docs.rs-auto__enums-blue?style=flat-square&logo=docs.rs)](https://docs.rs/auto_enums) [![license](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue?style=flat-square)](#license) [![msrv](https://img.shields.io/badge/msrv-1.56-blue?style=flat-square&logo=rust)](https://www.rust-lang.org) [![github actions](https://img.shields.io/github/actions/workflow/status/taiki-e/auto_enums/ci.yml?branch=main&style=flat-square&logo=github)](https://github.com/taiki-e/auto_enums/actions) A library for to allow multiple return types by automatically generated enum. This crate is a procedural macro implementation of the features discussions in [rust-lang/rfcs#2414]. This idea is also known as ["Anonymous sum types"][rust-lang/rfcs#294]. This library provides the following attribute macros: - `#[auto_enum]` Parses syntax, creates the enum, inserts variants, and passes specified traits to `#[enum_derive]`. - `#[enum_derive]` Implements specified traits to the enum. ## Usage Add this to your `Cargo.toml`: ```toml [dependencies] auto_enums = "0.8" ``` ## Examples `#[auto_enum]`'s basic feature is to wrap the value returned by the obvious branches (`match`, `if`, `return`, etc..) by an enum that implemented the specified traits. ```rust use auto_enums::auto_enum; #[auto_enum(Iterator)] fn foo(x: i32) -> impl Iterator { match x { 0 => 1..10, _ => vec![5, 10].into_iter(), } } ``` `#[auto_enum]` generates code in two stages. First, `#[auto_enum]` will do the following. - parses syntax - creates the enum - inserts variants Code like this will be generated: ```rust fn foo(x: i32) -> impl Iterator { #[::auto_enums::enum_derive(Iterator)] enum __Enum1<__T1, __T2> { __T1(__T1), __T2(__T2), } match x { 0 => __Enum1::__T1(1..10), _ => __Enum1::__T2(vec![5, 10].into_iter()), } } ``` Next, `#[enum_derive]` implements the specified traits. [Code like this will be generated](tests/expand/enum_derive/example-1.expanded.rs) `#[auto_enum]` can also parse nested arms/branches by using the `#[nested]` attribute. ```rust use auto_enums::auto_enum; #[auto_enum(Iterator)] fn foo(x: i32) -> impl Iterator { match x { 0 => 1..10, #[nested] _ => match x { 1 => vec![5, 10].into_iter(), _ => 0..=x, }, } } ``` See [documentation](https://docs.rs/auto_enums) for more details. ## Supported traits `#[enum_derive]` implements the supported traits and passes unsupported traits to `#[derive]`. `#[enum_derive]` supports many of the standard library traits and some popular third-party libraries traits such as [rayon], [futures][futures03], [tokio][tokio1], [http_body][http_body1]. **See [documentation](https://docs.rs/auto_enums/latest/auto_enums/#supported-traits) for a complete list of supported traits.** If you want to use traits that are not supported by `#[enum_derive]`, you can use another crate that provides [derives macros][proc-macro-derive], or you can define derives macros yourself ([derive_utils] probably can help it). Basic usage of `#[enum_derive]` ```rust use auto_enums::enum_derive; // `#[enum_derive]` implements `Iterator`, and `#[derive]` implements `Clone`. #[enum_derive(Iterator, Clone)] enum Foo { A(A), B(B), } ``` ## Optional features - **`std`** *(enabled by default)* - Enable to use `std` library's traits. - **`ops`** - Enable to use `[std|core]::ops`'s `Deref`, `DerefMut`, `Index`, `IndexMut`, and `RangeBounds` traits. - **`convert`** - Enable to use `[std|core]::convert`'s `AsRef` and `AsMut` traits. - **`fmt`** - Enable to use `[std|core]::fmt`'s traits other than `Debug`, `Display` and `Write`. - **`transpose_methods`** - Enable to use `transpose*` methods. - **`futures03`** - Enable to use [futures v0.3][futures03] traits. - **`futures01`** - Enable to use [futures v0.1][futures01] traits. - **`rayon`** - Enable to use [rayon] traits. - **`serde`** - Enable to use [serde] traits. - **`tokio1`** - Enable to use [tokio v1][tokio1] traits. - **`tokio03`** - Enable to use [tokio v0.3][tokio03] traits. - **`tokio02`** - Enable to use [tokio v0.2][tokio02] traits. - **`tokio01`** - Enable to use [tokio v0.1][tokio01] traits. - **`http_body1`** - Enable to use [http_body v1][http_body1] traits. - **`coroutine_trait`** - Enable to use `[std|core]::ops::Coroutine` trait. - Note that this feature is unstable and may cause incompatible changes between patch versions. - **`fn_traits`** - Enable to use `[std|core]::ops`'s `Fn`, `FnMut`, and `FnOnce` traits. - Note that this feature is unstable and may cause incompatible changes between patch versions. - **`trusted_len`** - Enable to use `[std|core]::iter::TrustedLen` trait. - Note that this feature is unstable and may cause incompatible changes between patch versions. ### `type_analysis` feature Analyze return type of function and `let` binding. *Note that this feature is still experimental.* Examples: ```rust use auto_enums::auto_enum; #[auto_enum] // there is no need to specify std library's traits fn func1(x: i32) -> impl Iterator { match x { 0 => 1..10, _ => vec![5, 10].into_iter(), } } #[auto_enum] fn func2(x: i32) { // Unlike `feature(impl_trait_in_bindings)`, this works on stable compilers. #[auto_enum] let iter: impl Iterator = match x { 0 => Some(0).into_iter(), _ => 0..x, }; } ``` Please be careful if you return another traits with the same name. ## Related Projects - [derive_utils]: A procedural macro helper for easily writing [derives macros][proc-macro-derive] for enums. - [io-enum]: \#\[derive(Read, Write, Seek, BufRead)\] for enums. - [iter-enum]: \#\[derive(Iterator, DoubleEndedIterator, ExactSizeIterator, Extend)\] for enums. [derive_utils]: https://github.com/taiki-e/derive_utils [futures01]: https://docs.rs/futures/0.1 [futures03]: https://docs.rs/futures/0.3 [io-enum]: https://github.com/taiki-e/io-enum [iter-enum]: https://github.com/taiki-e/iter-enum [proc-macro-derive]: https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros [rayon]: https://docs.rs/rayon/1 [rust-lang/rfcs#294]: https://github.com/rust-lang/rfcs/issues/294 [rust-lang/rfcs#2414]: https://github.com/rust-lang/rfcs/issues/2414 [serde]: https://docs.rs/serde/1 [tokio01]: https://docs.rs/tokio/0.1 [tokio02]: https://docs.rs/tokio/0.2 [tokio03]: https://docs.rs/tokio/0.3 [tokio1]: https://docs.rs/tokio/1 [http_body1]: https://docs.rs/http_body/1 ## License Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or [MIT license](LICENSE-MIT) at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. auto_enums-0.8.7/src/auto_enum/context.rs000064400000000000000000000271001046102023000166340ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use std::{ cell::RefCell, collections::hash_map::DefaultHasher, hash::Hasher as _, iter, mem, thread, }; use proc_macro2::TokenStream; use quote::format_ident; #[cfg(feature = "type_analysis")] use syn::Type; use syn::{ parse::{Parse, ParseStream}, parse_quote, Attribute, Error, Expr, Ident, ItemEnum, Macro, Path, Result, Token, }; use super::visitor::{Dummy, Visitor}; use crate::utils::{expr_call, path, replace_expr, unit, Node}; // ----------------------------------------------------------------------------- // Context /// Config for related to `visitor::Visitor` type. #[derive(Clone, Copy, PartialEq)] pub(super) enum VisitMode { Default, Return(/* count */ usize), Try, } /// Config for related to `expr::child_expr`. #[derive(Clone, Copy, PartialEq)] pub(super) enum VisitLastMode { Default, /* local: `let .. = || {};` or expr: `|| {}` not item_fn: `fn _() -> Fn*() { || {} }` */ /// `Stmt::Semi(..)` - never visit last expr Never, } /// The default identifier of expression level marker. pub(super) const DEFAULT_MARKER: &str = "marker"; pub(super) struct Context { builder: Builder, /// The identifier of the marker macro of the current scope. pub(super) current_marker: String, /// All marker macro identifiers that may have effects on the current scope. markers: Vec, // TODO: we may be able to replace some fields based on depth. // depth: isize, /// Currently, this is basically the same as `self.markers.len() == 1`. root: bool, /// This is `true` if other `auto_enum` attribute exists in the current scope. pub(super) has_child: bool, pub(super) visit_mode: VisitMode, pub(super) visit_last_mode: VisitLastMode, /// Span passed to `syn::Error::new_spanned`. pub(super) span: TokenStream, // - `None`: during checking. // - `Some(None)`: there are no errors. // - `Some(Some)`: there are errors. #[allow(clippy::option_option)] error: RefCell>>, pub(super) args: Vec, // if "type_analysis" feature is disabled, this field is always empty. traits: Vec, } impl Context { fn new( span: TokenStream, args: TokenStream, root: bool, mut markers: Vec, diagnostic: Option, ) -> Result { let Args { args, marker } = syn::parse2(args)?; let current_marker = if let Some(marker) = marker { // Currently, there is no reason to preserve the span, so convert `Ident` to `String`. // This should probably be more efficient than calling `to_string` for each comparison. // https://github.com/dtolnay/proc-macro2/blob/1.0.86/src/wrapper.rs#L723 let marker_string = marker.to_string(); if markers.contains(&marker_string) { bail!( marker, "a custom marker name is specified that duplicated the name already used in the parent scope", ); } marker_string } else { DEFAULT_MARKER.to_owned() }; markers.push(current_marker.clone()); Ok(Self { builder: Builder::new(&span), current_marker, markers, root, has_child: false, visit_mode: VisitMode::Default, visit_last_mode: VisitLastMode::Default, span, error: RefCell::new(Some(diagnostic)), args, traits: vec![], }) } /// Make a new `Context` as a root. pub(super) fn root(span: TokenStream, args: TokenStream) -> Result { Self::new(span, args, true, Vec::with_capacity(1), None) } /// Make a new `Context` as a child based on a parent context `self`. pub(super) fn make_child(&mut self, span: TokenStream, args: TokenStream) -> Result { debug_assert!(self.has_child); Self::new( span, args, false, mem::take(&mut self.markers), self.error.borrow_mut().as_mut().unwrap().take(), ) } /// Merge a child `Context` into a parent context `self`. pub(super) fn join_child(&mut self, mut child: Self) { debug_assert!(self.markers.is_empty()); child.markers.pop(); mem::swap(&mut self.markers, &mut child.markers); if let Some(message) = child.error.borrow_mut().take().unwrap() { self.error(message); } } pub(super) fn error(&self, message: Error) { match self.error.borrow_mut().as_mut().unwrap() { Some(base) => base.combine(message), error @ None => *error = Some(message), } } pub(super) fn check(self) -> Result<()> { match self.error.borrow_mut().take().unwrap() { Some(e) => Err(e), None => Ok(()), } } /// Returns `true` if one or more errors occurred. pub(super) fn has_error(&self) -> bool { self.error.borrow().as_ref().unwrap().is_some() } pub(super) fn visit_last(&self) -> bool { self.visit_last_mode != VisitLastMode::Never && self.visit_mode != VisitMode::Try } /// Even if this is `false`, there are cases where this `auto_enum` attribute is handled as a /// dummy. e.g., If `self.has_child && self.builder.variants.is_empty()` is true, this /// `auto_enum` attribute is handled as a dummy. pub(super) fn is_dummy(&self) -> bool { // `auto_enum` attribute with no argument is handled as a dummy. // if "type_analysis" feature is disabled, `self.traits` field is always empty. self.args.is_empty() && self.traits.is_empty() } #[cfg(feature = "type_analysis")] pub(super) fn variant_is_empty(&self) -> bool { self.builder.variants.is_empty() } /// Returns `true` if `expr` is the marker macro that may have effects on the current scope. pub(super) fn is_marker_expr(&self, expr: &Expr) -> bool { match expr { Expr::Macro(expr) => self.is_marker_macro(&expr.mac), _ => false, } } /// Returns `true` if `mac` is the marker macro that may have effects on the current scope. pub(super) fn is_marker_macro(&self, mac: &Macro) -> bool { let exact = self.is_marker_macro_exact(mac); if exact || self.root { return exact; } self.markers.iter().any(|marker| mac.path.is_ident(marker)) } /// Returns `true` if `mac` is the marker macro of the current scope. pub(super) fn is_marker_macro_exact(&self, mac: &Macro) -> bool { mac.path.is_ident(&self.current_marker) } /// from `` into `Enum::VariantN()` pub(super) fn next_expr(&mut self, expr: Expr) -> Expr { self.next_expr_with_attrs(vec![], expr) } /// from `` into ` Enum::VariantN()` pub(super) fn next_expr_with_attrs(&mut self, attrs: Vec, expr: Expr) -> Expr { self.builder.next_expr(attrs, expr) } pub(super) fn replace_boxed_expr(&mut self, expr: &mut Option>) { replace_expr(expr.get_or_insert_with(|| Box::new(unit())), |expr| { if self.is_marker_expr(&expr) { // Skip if `` is a marker macro. expr } else { self.next_expr(expr) } }); } // visitors pub(super) fn visitor(&mut self, node: &mut impl Node) { node.visited(&mut Visitor::new(self)); } pub(super) fn dummy(&mut self, node: &mut impl Node) { debug_assert!(self.args.is_empty()); node.visited(&mut Dummy::new(self)); } // build pub(super) fn build(&self, f: impl FnOnce(ItemEnum)) { // As we know that an error will occur, it does not matter if there are not enough variants. if !self.has_error() { match self.builder.variants.len() { 1 => {} 0 if !self.has_child => {} _ => { if !self.builder.variants.is_empty() { f(self.builder.build(&self.args, &self.traits)); } return; } } let (msg1, msg2) = match self.visit_last_mode { VisitLastMode::Default => { ("branches or marker macros in total", "branch or marker macro") } VisitLastMode::Never => ("marker macros", "marker macro"), }; self.error(format_err!( self.span, "`#[auto_enum]` is required two or more {}, there is {} {} in this statement", msg1, if self.builder.variants.is_empty() { "no" } else { "only one" }, msg2 )); } } // type_analysis feature #[cfg(feature = "type_analysis")] pub(super) fn collect_impl_trait(&mut self, ty: &mut Type) -> bool { super::type_analysis::collect_impl_trait(&self.args, &mut self.traits, ty) } } impl Drop for Context { fn drop(&mut self) { if !thread::panicking() && self.error.borrow().is_some() { panic!("context need to be checked"); } } } // ----------------------------------------------------------------------------- // Args mod kw { syn::custom_keyword!(marker); } struct Args { args: Vec, marker: Option, } impl Parse for Args { fn parse(input: ParseStream<'_>) -> Result { let mut args = Vec::with_capacity((!input.is_empty()) as usize); let mut marker = None; while !input.is_empty() { if input.peek(kw::marker) && input.peek2(Token![=]) { let i: kw::marker = input.parse()?; let _: Token![=] = input.parse()?; let ident: Ident = input.parse()?; if marker.replace(ident).is_some() { bail!(i, "duplicate `marker` argument"); } } else { args.push(input.parse()?); } if input.is_empty() { break; } let _: Token![,] = input.parse()?; } Ok(Self { args, marker }) } } // ----------------------------------------------------------------------------- // Enum builder struct Builder { ident: Ident, variants: Vec, } impl Builder { fn new(input: &TokenStream) -> Self { Self { ident: format_ident!("__Enum{}", hash(input)), variants: Vec::with_capacity(2) } } fn next_expr(&mut self, attrs: Vec, expr: Expr) -> Expr { let variant = format_ident!("__Variant{}", self.variants.len()); let path = path(iter::once(self.ident.clone().into()).chain(iter::once(variant.clone().into()))); self.variants.push(variant); expr_call(attrs, path, expr) } fn build(&self, args: &[Path], traits: &[Path]) -> ItemEnum { let derive = args.iter().chain(traits); let ident = &self.ident; let ty_generics = &self.variants; let variants = &self.variants; let fields = &self.variants; parse_quote! { #[allow(non_camel_case_types)] #[::auto_enums::enum_derive(#(#derive),*)] enum #ident<#(#ty_generics),*> { #(#variants(#fields),)* } } } } /// Returns the hash value of the input AST. fn hash(input: &TokenStream) -> u64 { let mut hasher = DefaultHasher::new(); hasher.write(input.to_string().as_bytes()); hasher.finish() } auto_enums-0.8.7/src/auto_enum/expr.rs000064400000000000000000000155101046102023000161300ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use syn::{ visit_mut::{self, VisitMut}, Arm, Block, Expr, ExprBlock, ExprBreak, ExprCall, ExprIf, ExprLoop, ExprMacro, ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprTry, ExprUnsafe, Item, Label, Lifetime, LocalInit, Macro, Stmt, StmtMacro, Token, }; use super::{visitor, Context, NAME, NESTED, NEVER}; use crate::utils::{expr_block, path_eq, replace_block, replace_expr, Attrs as _}; /// Visits last expression. /// /// Note that do not use this after `cx.visitor()`. pub(super) fn child_expr(cx: &mut Context, expr: &mut Expr) { if !cx.visit_last() || is_unreachable(cx, expr) { return; } match expr { Expr::Block(ExprBlock { block, .. }) | Expr::Unsafe(ExprUnsafe { block, .. }) => { if let Some(Stmt::Expr(expr, None)) = block.stmts.last_mut() { child_expr(cx, expr); } } Expr::Match(expr) => visit_last_expr_match(cx, expr), Expr::If(expr) => visit_last_expr_if(cx, expr), Expr::Loop(expr) => visit_last_expr_loop(cx, expr), // Search recursively Expr::MethodCall(ExprMethodCall { receiver: expr, .. }) | Expr::Paren(ExprParen { expr, .. }) => child_expr(cx, expr), _ => {} } } pub(super) fn is_unreachable(cx: &Context, expr: &Expr) -> bool { if expr.any_empty_attr(NEVER) || expr.any_attr(NAME) { return true; } match expr { Expr::Block(ExprBlock { block, .. }) | Expr::Unsafe(ExprUnsafe { block, .. }) => { is_unreachable_stmt(cx, block.stmts.last()) } Expr::Break(_) | Expr::Continue(_) | Expr::Return(_) => true, Expr::Macro(ExprMacro { mac, .. }) => is_unreachable_macro(cx, mac), Expr::Match(ExprMatch { arms, .. }) => { arms.iter().all(|arm| arm.any_empty_attr(NEVER) || is_unreachable(cx, &arm.body)) } // `Err(expr)?` or `None?`. Expr::Try(ExprTry { expr, .. }) => match &**expr { Expr::Path(ExprPath { path, qself: None, .. }) => { path_eq(path, &["std", "core"], &["option", "Option", "None"]) } Expr::Call(ExprCall { args, func, .. }) if args.len() == 1 => match &**func { Expr::Path(ExprPath { path, qself: None, .. }) => { path_eq(path, &["std", "core"], &["result", "Result", "Err"]) } _ => false, }, _ => false, }, // Search recursively Expr::MethodCall(ExprMethodCall { receiver: expr, .. }) | Expr::Paren(ExprParen { expr, .. }) => is_unreachable(cx, expr), _ => false, } } fn is_unreachable_macro(cx: &Context, mac: &Macro) -> bool { const UNREACHABLE_MACROS: &[&str] = &["unreachable", "panic"]; // `unreachable!`, `panic!` or an expression level marker (`marker!` macro). UNREACHABLE_MACROS.iter().any(|i| path_eq(&mac.path, &["std", "core"], &[i])) || cx.is_marker_macro(mac) } fn is_unreachable_stmt(cx: &Context, stmt: Option<&Stmt>) -> bool { match stmt { Some(Stmt::Expr(expr, _)) => is_unreachable(cx, expr), Some(Stmt::Local(local)) => { local.init.as_ref().map_or(false, |LocalInit { expr, .. }| is_unreachable(cx, expr)) } Some(Stmt::Item(_)) => true, Some(Stmt::Macro(StmtMacro { mac, .. })) => is_unreachable_macro(cx, mac), None => false, } } fn visit_last_expr_match(cx: &mut Context, expr: &mut ExprMatch) { fn skip(cx: &Context, arm: &mut Arm) -> bool { arm.any_empty_attr(NEVER) || arm.any_empty_attr(NESTED) || is_unreachable(cx, &arm.body) || visitor::find_nested(arm) } for arm in &mut expr.arms { if !skip(cx, arm) { arm.comma = Some(::default()); replace_expr(&mut arm.body, |x| cx.next_expr(x)); } } } fn visit_last_expr_if(cx: &mut Context, expr: &mut ExprIf) { fn skip(cx: &Context, block: &mut Block) -> bool { match block.stmts.last_mut() { Some(Stmt::Expr(expr, None)) => { expr.any_empty_attr(NESTED) || is_unreachable(cx, expr) || visitor::find_nested(block) } _ => is_unreachable_stmt(cx, block.stmts.last()), } } if !skip(cx, &mut expr.then_branch) { replace_block(&mut expr.then_branch, |b| cx.next_expr(expr_block(b))); } match expr.else_branch.as_mut().map(|(_, expr)| &mut **expr) { Some(Expr::Block(expr)) => { if !skip(cx, &mut expr.block) { replace_block(&mut expr.block, |b| cx.next_expr(expr_block(b))); } } Some(Expr::If(expr)) => visit_last_expr_if(cx, expr), // TODO: https://docs.rs/proc-macro2/1/proc_macro2/struct.Span.html#method.join // `expr.span().join(expr.then_branch.span()).unwrap_or_else(|| expr.span())`` None => cx.error(format_err!(expr.if_token, "`if` expression missing an else clause")), Some(_) => unreachable!("wrong_if"), } } fn visit_last_expr_loop(cx: &mut Context, expr: &mut ExprLoop) { struct LoopVisitor<'a> { cx: &'a mut Context, label: Option<&'a Label>, nested: bool, } impl LoopVisitor<'_> { fn compare_labels(&self, other: Option<&Lifetime>) -> bool { match (self.label, other) { (None, None) => true, (Some(this), Some(other)) => this.name.ident == other.ident, _ => false, } } } impl VisitMut for LoopVisitor<'_> { fn visit_expr_mut(&mut self, node: &mut Expr) { if node.any_empty_attr(NEVER) { return; } let tmp = self.nested; match node { // Stop at closure / async block bounds Expr::Closure(_) | Expr::Async(_) => return, // Other loop bounds Expr::Loop(_) | Expr::ForLoop(_) | Expr::While(_) => { if self.label.is_none() { return; } self.nested = true; } // Desugar `break ` into `break Enum::VariantN()`. Expr::Break(ExprBreak { label, expr, .. }) => { if !self.nested && label.is_none() || self.compare_labels(label.as_ref()) { self.cx.replace_boxed_expr(expr); } } _ => {} } visit_mut::visit_expr_mut(self, node); self.nested = tmp; } fn visit_item_mut(&mut self, _: &mut Item) { // Do not recurse into nested items. } } LoopVisitor { cx, label: expr.label.as_ref(), nested: false }.visit_block_mut(&mut expr.body); } auto_enums-0.8.7/src/auto_enum/mod.rs000064400000000000000000000152401046102023000157310ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT mod context; mod expr; #[cfg(feature = "type_analysis")] mod type_analysis; mod visitor; use proc_macro2::TokenStream; use quote::ToTokens as _; #[cfg(feature = "type_analysis")] use syn::Pat; use syn::{ AngleBracketedGenericArguments, Error, Expr, ExprClosure, GenericArgument, Item, ItemEnum, ItemFn, Local, LocalInit, PathArguments, ReturnType, Stmt, Type, TypePath, }; use self::{ context::{Context, VisitLastMode, VisitMode, DEFAULT_MARKER}, expr::child_expr, }; use crate::utils::{block, expr_block, path_eq, replace_expr}; /// The attribute name. const NAME: &str = "auto_enum"; /// The annotation for recursively parsing. const NESTED: &str = "nested"; /// The annotation for skipping branch. const NEVER: &str = "never"; pub(crate) fn attribute(args: TokenStream, input: TokenStream) -> TokenStream { let mut cx = match Context::root(input.clone(), args) { Ok(cx) => cx, Err(e) => return e.to_compile_error(), }; match syn::parse2::(input.clone()) { Ok(mut stmt) => { expand_parent_stmt(&mut cx, &mut stmt); cx.check().map(|()| stmt.into_token_stream()) } Err(e) => match syn::parse2::(input) { Err(_e) => { cx.error(e); cx.error(format_err!( cx.span, "may only be used on expression, statement, or function" )); cx.check().map(|()| unreachable!()) } Ok(mut expr) => { expand_parent_expr(&mut cx, &mut expr, false); cx.check().map(|()| expr.into_token_stream()) } }, } .unwrap_or_else(Error::into_compile_error) } fn expand_expr(cx: &mut Context, expr: &mut Expr) { let expr = match expr { Expr::Closure(ExprClosure { body, .. }) if cx.visit_last() => { let count = visitor::visit_fn(cx, &mut **body); if count.try_ >= 2 { cx.visit_mode = VisitMode::Try; } else { cx.visit_mode = VisitMode::Return(count.return_); } &mut **body } _ => expr, }; child_expr(cx, expr); #[cfg(feature = "type_analysis")] { if let VisitMode::Return(count) = cx.visit_mode { if cx.args.is_empty() && cx.variant_is_empty() && count < 2 { cx.dummy(expr); return; } } } cx.visitor(expr); } fn build_expr(expr: &mut Expr, item: ItemEnum) { replace_expr(expr, |expr| { expr_block(block(vec![Stmt::Item(item.into()), Stmt::Expr(expr, None)])) }); } // ----------------------------------------------------------------------------- // Expand statement or expression in which `#[auto_enum]` was directly used. fn expand_parent_stmt(cx: &mut Context, stmt: &mut Stmt) { match stmt { Stmt::Expr(expr, semi) => expand_parent_expr(cx, expr, semi.is_some()), Stmt::Local(local) => expand_parent_local(cx, local), Stmt::Item(Item::Fn(item)) => expand_parent_item_fn(cx, item), Stmt::Item(item) => { cx.error(format_err!(item, "may only be used on expression, statement, or function")); } Stmt::Macro(_) => {} } } fn expand_parent_expr(cx: &mut Context, expr: &mut Expr, has_semi: bool) { if has_semi { cx.visit_last_mode = VisitLastMode::Never; } if cx.is_dummy() { cx.dummy(expr); return; } expand_expr(cx, expr); cx.build(|item| build_expr(expr, item)); } fn expand_parent_local(cx: &mut Context, local: &mut Local) { #[cfg(feature = "type_analysis")] { if let Pat::Type(pat) = &mut local.pat { if cx.collect_impl_trait(&mut pat.ty) { local.pat = (*pat.pat).clone(); } } } if cx.is_dummy() { cx.dummy(local); return; } let expr = if let Some(LocalInit { expr, .. }) = &mut local.init { &mut **expr } else { cx.error(format_err!( local, "the `#[auto_enum]` attribute is not supported uninitialized let statement" )); return; }; expand_expr(cx, expr); cx.build(|item| build_expr(expr, item)); } fn expand_parent_item_fn(cx: &mut Context, item: &mut ItemFn) { let ItemFn { sig, block, .. } = item; if let ReturnType::Type(_, ty) = &mut sig.output { match &**ty { // `return` Type::ImplTrait(_) if cx.visit_last_mode != VisitLastMode::Never => { let count = visitor::visit_fn(cx, &mut **block); cx.visit_mode = VisitMode::Return(count.return_); } // `?` operator Type::Path(TypePath { qself: None, path }) if cx.visit_last_mode != VisitLastMode::Never => { let ty = path.segments.last().unwrap(); match &ty.arguments { // `Result` PathArguments::AngleBracketed(AngleBracketedGenericArguments { colon2_token: None, args, .. }) if args.len() == 2 && path_eq(path, &["std", "core"], &["result", "Result"]) => { if let ( GenericArgument::Type(_), GenericArgument::Type(Type::ImplTrait(_)), ) = (&args[0], &args[1]) { let count = visitor::visit_fn(cx, &mut **block); if count.try_ >= 2 { cx.visit_mode = VisitMode::Try; } } } _ => {} } } _ => {} } #[cfg(feature = "type_analysis")] cx.collect_impl_trait(&mut *ty); } if cx.is_dummy() { cx.dummy(item); return; } match item.block.stmts.last_mut() { Some(Stmt::Expr(expr, None)) => child_expr(cx, expr), Some(_) => {} None => cx.error(format_err!( item.block, "the `#[auto_enum]` attribute is not supported empty functions" )), } #[cfg(feature = "type_analysis")] { if let VisitMode::Return(count) = cx.visit_mode { if cx.args.is_empty() && cx.variant_is_empty() && count < 2 { cx.dummy(item); return; } } } cx.visitor(item); cx.build(|i| item.block.stmts.insert(0, Stmt::Item(i.into()))); } auto_enums-0.8.7/src/auto_enum/type_analysis.rs000064400000000000000000000042551046102023000200420ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use quote::ToTokens as _; use syn::{ visit_mut::{self, VisitMut}, Path, Type, TypeImplTrait, TypeParamBound, }; use crate::utils::path; pub(super) fn collect_impl_trait(args: &[Path], traits: &mut Vec, ty: &mut Type) -> bool { struct CollectImplTrait<'a> { args: &'a [Path], traits: &'a mut Vec, has_impl_trait: bool, } impl VisitMut for CollectImplTrait<'_> { fn visit_type_impl_trait_mut(&mut self, node: &mut TypeImplTrait) { visit_mut::visit_type_impl_trait_mut(self, node); for ty in &node.bounds { if let TypeParamBound::Trait(ty) = ty { let ty = path(ty.path.segments.iter().map(|ty| ty.ident.clone().into())); let ty_str = ty.to_token_stream().to_string(); let ty_trimmed = ty_str.replace(' ', ""); if TRAITS.contains(&&*ty_trimmed) && !self.args.iter().any(|x| x.to_token_stream().to_string() == ty_str) { self.has_impl_trait = true; self.traits.push(ty); } } } } } let mut visitor = CollectImplTrait { args, traits, has_impl_trait: false }; visitor.visit_type_mut(ty); visitor.has_impl_trait } const TRAITS: &[&str] = &[ "Clone", "Copy", "PartialEq", "Eq", "PartialOrd", "Ord", "Hash", // core "AsRef", "AsMut", "Debug", "fmt::Debug", "Display", "fmt::Display", "fmt::Binary", "fmt::LowerExp", "fmt::LowerHex", "fmt::Octal", "fmt::Pointer", "fmt::UpperExp", "fmt::UpperHex", "fmt::Write", "Iterator", "DoubleEndedIterator", "ExactSizeIterator", "FusedIterator", "TrustedLen", "Extend", "Deref", "DerefMut", "Index", "IndexMut", "RangeBounds", "Fn", "FnMut", "FnOnce", "Coroutine", "Future", // std "Read", "io::Read", "BufRead", "io::BufRead", "Write", "io::Write", "Seek", "io::Seek", "Error", "error::Error", ]; auto_enums-0.8.7/src/auto_enum/visitor.rs000064400000000000000000000356471046102023000166660ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use proc_macro2::TokenStream; use quote::ToTokens as _; use syn::{ parse_quote, token, visit_mut::{self, VisitMut}, Arm, Attribute, Expr, ExprMacro, ExprMatch, ExprReturn, ExprTry, Item, Local, LocalInit, MetaList, Stmt, Token, }; use super::{Context, VisitMode, DEFAULT_MARKER, NAME, NESTED, NEVER}; use crate::utils::{replace_expr, Attrs, Node}; #[derive(Clone, Copy, Default)] struct Scope { /// in closures closure: bool, /// in try blocks try_block: bool, /// in the other `auto_enum` attributes foreign: bool, } impl Scope { // check this scope is in closures or try blocks. fn check_expr(&mut self, expr: &Expr) { match expr { Expr::Closure(_) => self.closure = true, // `?` operator in try blocks are not supported. Expr::TryBlock(_) => self.try_block = true, _ => {} } } } // ----------------------------------------------------------------------------- // default visitor pub(super) struct Visitor<'a> { cx: &'a mut Context, scope: Scope, } impl<'a> Visitor<'a> { pub(super) fn new(cx: &'a mut Context) -> Self { Self { cx, scope: Scope::default() } } fn find_remove_attrs(&self, attrs: &mut impl Attrs) { if !self.scope.foreign { if let Some(attr) = attrs.find_remove_attr(NEVER) { if let Err(e) = attr.meta.require_path_only() { self.cx.error(e); } } // The old annotation `#[rec]` is replaced with `#[nested]`. if let Some(old) = attrs.find_remove_attr("rec") { self.cx.error(format_err!( old, "#[rec] has been removed and replaced with #[{}]", NESTED )); } } } /// `return` in functions or closures fn visit_return(&mut self, node: &mut Expr, count: usize) { debug_assert!(self.cx.visit_mode == VisitMode::Return(count)); if !self.scope.closure && !node.any_empty_attr(NEVER) { // Desugar `return ` into `return Enum::VariantN()`. if let Expr::Return(ExprReturn { expr, .. }) = node { // Skip if `` is a marker macro. if expr.as_ref().map_or(true, |expr| !self.cx.is_marker_expr(expr)) { self.cx.replace_boxed_expr(expr); } } } } /// `?` operator in functions or closures fn visit_try(&mut self, node: &mut Expr) { debug_assert!(self.cx.visit_mode == VisitMode::Try); if !self.scope.try_block && !self.scope.closure && !node.any_empty_attr(NEVER) { match &node { // https://github.com/rust-lang/rust/blob/1.35.0/src/librustc/hir/lowering.rs#L4578-L4682 // Desugar `?` // into: // // match { // Ok(val) => val, // Err(err) => return Err(Enum::VariantN(err)), // } // // Skip if `` is a marker macro. Expr::Try(ExprTry { expr, .. }) if !self.cx.is_marker_expr(expr) => { replace_expr(node, |expr| { let ExprTry { attrs, expr, .. } = if let Expr::Try(expr) = expr { expr } else { unreachable!() }; let err = self.cx.next_expr(parse_quote!(err)); let arms = vec![ parse_quote! { ::core::result::Result::Ok(val) => val, }, parse_quote! { ::core::result::Result::Err(err) => { return ::core::result::Result::Err(#err); } }, ]; Expr::Match(ExprMatch { attrs, match_token: ::default(), expr, brace_token: token::Brace::default(), arms, }) }); } _ => {} } } } /// `#[nested]` fn visit_nested(&mut self, node: &mut Expr, attr: &Attribute) { debug_assert!(!self.scope.foreign); if let Err(e) = attr.meta.require_path_only() { self.cx.error(e); } else { super::expr::child_expr(self.cx, node); } } /// Expression level marker (`marker!` macro) fn visit_marker_macro(&mut self, node: &mut Expr) { debug_assert!(!self.scope.foreign || self.cx.current_marker != DEFAULT_MARKER); match node { // Desugar `marker!()` into `Enum::VariantN()`. // Skip if `marker!` is not a marker macro. Expr::Macro(ExprMacro { mac, .. }) if self.cx.is_marker_macro_exact(mac) => { replace_expr(node, |expr| { let expr = if let Expr::Macro(expr) = expr { expr } else { unreachable!() }; let args = syn::parse2(expr.mac.tokens).unwrap_or_else(|e| { self.cx.error(e); // Generate an expression to fill in where the error occurred during the visit. // These will eventually need to be replaced with the original error message. parse_quote!(compile_error!( "#[auto_enum] failed to generate error message" )) }); if self.cx.has_error() { args } else { self.cx.next_expr_with_attrs(expr.attrs, args) } }); } _ => {} } } fn visit_expr(&mut self, node: &mut Expr, has_semi: bool) { debug_assert!(!self.cx.has_error()); let tmp = self.scope; if node.any_attr(NAME) { self.scope.foreign = true; // Record whether other `auto_enum` attribute exists. self.cx.has_child = true; } self.scope.check_expr(node); match self.cx.visit_mode { VisitMode::Return(count) => self.visit_return(node, count), VisitMode::Try => self.visit_try(node), VisitMode::Default => {} } if !self.scope.foreign { if let Some(attr) = node.find_remove_attr(NESTED) { self.visit_nested(node, &attr); } } VisitStmt::visit_expr(self, node, has_semi); if !self.scope.foreign || self.cx.current_marker != DEFAULT_MARKER { self.visit_marker_macro(node); self.find_remove_attrs(node); } self.scope = tmp; } } impl VisitMut for Visitor<'_> { fn visit_expr_mut(&mut self, node: &mut Expr) { if !self.cx.has_error() { self.visit_expr(node, false); } } fn visit_arm_mut(&mut self, node: &mut Arm) { if !self.cx.has_error() { if !self.scope.foreign { if let Some(attr) = node.find_remove_attr(NESTED) { self.visit_nested(&mut node.body, &attr); } } visit_mut::visit_arm_mut(self, node); self.find_remove_attrs(node); } } fn visit_local_mut(&mut self, node: &mut Local) { if !self.cx.has_error() { if !self.scope.foreign { if let Some(attr) = node.find_remove_attr(NESTED) { if let Some(LocalInit { expr, .. }) = &mut node.init { self.visit_nested(expr, &attr); } } } visit_mut::visit_local_mut(self, node); self.find_remove_attrs(node); } } fn visit_stmt_mut(&mut self, node: &mut Stmt) { if !self.cx.has_error() { if let Stmt::Expr(expr, semi) = node { self.visit_expr(expr, semi.is_some()); } else { let tmp = self.scope; if node.any_attr(NAME) { self.scope.foreign = true; // Record whether other `auto_enum` attribute exists. self.cx.has_child = true; } VisitStmt::visit_stmt(self, node); self.scope = tmp; } } } fn visit_item_mut(&mut self, _: &mut Item) { // Do not recurse into nested items. } } impl VisitStmt for Visitor<'_> { fn cx(&mut self) -> &mut Context { self.cx } } // ----------------------------------------------------------------------------- // dummy visitor pub(super) struct Dummy<'a> { cx: &'a mut Context, } impl<'a> Dummy<'a> { pub(super) fn new(cx: &'a mut Context) -> Self { Self { cx } } } impl VisitMut for Dummy<'_> { fn visit_stmt_mut(&mut self, node: &mut Stmt) { if !self.cx.has_error() { if node.any_attr(NAME) { self.cx.has_child = true; } VisitStmt::visit_stmt(self, node); } } fn visit_expr_mut(&mut self, node: &mut Expr) { if !self.cx.has_error() { if node.any_attr(NAME) { self.cx.has_child = true; } VisitStmt::visit_expr(self, node, false); } } fn visit_item_mut(&mut self, _: &mut Item) { // Do not recurse into nested items. } } impl VisitStmt for Dummy<'_> { fn cx(&mut self) -> &mut Context { self.cx } } // ----------------------------------------------------------------------------- // VisitStmt trait VisitStmt: VisitMut { fn cx(&mut self) -> &mut Context; fn visit_expr(visitor: &mut Self, node: &mut Expr, has_semi: bool) { let attr = node.find_remove_attr(NAME); let res = attr.map(|attr| { attr.meta.require_list().and_then(|MetaList { tokens, .. }| { visitor.cx().make_child(node.to_token_stream(), tokens.clone()) }) }); visit_mut::visit_expr_mut(visitor, node); match res { Some(Err(e)) => visitor.cx().error(e), Some(Ok(mut cx)) => { super::expand_parent_expr(&mut cx, node, has_semi); visitor.cx().join_child(cx); } None => {} } } fn visit_stmt(visitor: &mut Self, node: &mut Stmt) { let attr = match node { Stmt::Expr(expr, semi) => { Self::visit_expr(visitor, expr, semi.is_some()); return; } Stmt::Local(local) => local.find_remove_attr(NAME), Stmt::Macro(_) => None, // Do not recurse into nested items. Stmt::Item(_) => return, }; let res = attr.map(|attr| { let args = match attr.meta { syn::Meta::Path(_) => TokenStream::new(), syn::Meta::List(list) => list.tokens, syn::Meta::NameValue(nv) => bail!(nv.eq_token, "expected list"), }; visitor.cx().make_child(node.to_token_stream(), args) }); visit_mut::visit_stmt_mut(visitor, node); match res { Some(Err(e)) => visitor.cx().error(e), Some(Ok(mut cx)) => { super::expand_parent_stmt(&mut cx, node); visitor.cx().join_child(cx); } None => {} } } } // ----------------------------------------------------------------------------- // FindNested /// Find `#[nested]` attribute. pub(super) fn find_nested(node: &mut impl Node) -> bool { struct FindNested { has: bool, } impl VisitMut for FindNested { fn visit_expr_mut(&mut self, node: &mut Expr) { if !node.any_attr(NAME) { if node.any_empty_attr(NESTED) { self.has = true; } else { visit_mut::visit_expr_mut(self, node); } } } fn visit_arm_mut(&mut self, node: &mut Arm) { if node.any_empty_attr(NESTED) { self.has = true; } else { visit_mut::visit_arm_mut(self, node); } } fn visit_local_mut(&mut self, node: &mut Local) { if !node.any_attr(NAME) { if node.any_empty_attr(NESTED) { self.has = true; } else { visit_mut::visit_local_mut(self, node); } } } fn visit_item_mut(&mut self, _: &mut Item) { // Do not recurse into nested items. } } let mut visitor = FindNested { has: false }; node.visited(&mut visitor); visitor.has } // ----------------------------------------------------------------------------- // FnVisitor #[derive(Default)] pub(super) struct FnCount { pub(super) try_: usize, pub(super) return_: usize, } pub(super) fn visit_fn(cx: &Context, node: &mut impl Node) -> FnCount { struct FnVisitor<'a> { cx: &'a Context, scope: Scope, count: FnCount, } impl VisitMut for FnVisitor<'_> { fn visit_expr_mut(&mut self, node: &mut Expr) { let tmp = self.scope; self.scope.check_expr(node); if !self.scope.closure && !node.any_empty_attr(NEVER) { match node { Expr::Try(ExprTry { expr, .. }) => { // Skip if `` is a marker macro. if !self.cx.is_marker_expr(expr) { self.count.try_ += 1; } } Expr::Return(ExprReturn { expr, .. }) => { // Skip if `` is a marker macro. if expr.as_ref().map_or(true, |expr| !self.cx.is_marker_expr(expr)) { self.count.return_ += 1; } } _ => {} } } if node.any_attr(NAME) { self.scope.foreign = true; } visit_mut::visit_expr_mut(self, node); self.scope = tmp; } fn visit_stmt_mut(&mut self, node: &mut Stmt) { let tmp = self.scope; if node.any_attr(NAME) { self.scope.foreign = true; } visit_mut::visit_stmt_mut(self, node); self.scope = tmp; } fn visit_item_mut(&mut self, _: &mut Item) { // Do not recurse into nested items. } } let mut visitor = FnVisitor { cx, scope: Scope::default(), count: FnCount::default() }; node.visited(&mut visitor); visitor.count } auto_enums-0.8.7/src/derive/core/convert.rs000064400000000000000000000015761046102023000170530ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT pub(crate) mod as_ref { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["AsRef"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::core::convert::AsRef), None, parse_quote! { trait AsRef<__T: ?Sized> { #[inline] fn as_ref(&self) -> &__T; } })) } } pub(crate) mod as_mut { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["AsMut"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::core::convert::AsMut), None, parse_quote! { trait AsMut<__T: ?Sized> { #[inline] fn as_mut(&mut self) -> &mut __T; } })) } } auto_enums-0.8.7/src/derive/core/fmt.rs000064400000000000000000000037001046102023000161500ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT macro_rules! derive_fmt { ($trait:ident, $Trait:ident, [$($name:expr),*]) => { pub(crate) mod $trait { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &[$($name),*]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::core::fmt::$Trait), None, parse_quote! { trait $Trait { #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result; } })) } } }; } derive_fmt!(debug, Debug, ["Debug", "fmt::Debug"]); derive_fmt!(display, Display, ["Display", "fmt::Display"]); #[cfg(feature = "fmt")] derive_fmt!(binary, Binary, ["fmt::Binary"]); #[cfg(feature = "fmt")] derive_fmt!(lower_exp, LowerExp, ["fmt::LowerExp"]); #[cfg(feature = "fmt")] derive_fmt!(lower_hex, LowerHex, ["fmt::LowerHex"]); #[cfg(feature = "fmt")] derive_fmt!(octal, Octal, ["fmt::Octal"]); #[cfg(feature = "fmt")] derive_fmt!(pointer, Pointer, ["fmt::Pointer"]); #[cfg(feature = "fmt")] derive_fmt!(upper_exp, UpperExp, ["fmt::UpperExp"]); #[cfg(feature = "fmt")] derive_fmt!(upper_hex, UpperHex, ["fmt::UpperHex"]); pub(crate) mod write { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["fmt::Write"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::core::fmt::Write), None, parse_quote! { trait Write { #[inline] fn write_str(&mut self, s: &str) -> ::core::fmt::Result; #[inline] fn write_char(&mut self, c: char) -> ::core::fmt::Result; #[inline] fn write_fmt(&mut self, args: ::core::fmt::Arguments<'_>) -> ::core::fmt::Result; } })) } } auto_enums-0.8.7/src/derive/core/future.rs000064400000000000000000000020471046102023000166770ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["Future"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::core::future::Future); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait Future { type Output; } }) .build_impl(); let poll = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { #[inline] fn poll( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll { unsafe { match self.get_unchecked_mut() { #(#poll)* } } } }); Ok(impl_.into_token_stream()) } auto_enums-0.8.7/src/derive/core/iter.rs000064400000000000000000000144601046102023000163320ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT pub(crate) mod iterator { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["Iterator"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { // TODO: Add try_fold once try_trait_v2 is stabilized https://github.com/rust-lang/rust/issues/84277 Ok(derive_trait(data, &parse_quote!(::core::iter::Iterator), None, parse_quote! { trait Iterator { type Item; #[inline] fn next(&mut self) -> ::core::option::Option; #[inline] fn size_hint(&self) -> (usize, ::core::option::Option); #[inline] fn count(self) -> usize; #[inline] fn last(self) -> ::core::option::Option; #[inline] fn nth(&mut self, n: usize) -> ::core::option::Option; #[inline] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] fn collect<__U: ::core::iter::FromIterator>(self) -> __U; #[inline] fn partition<__U, __F>(self, f: __F) -> (__U, __U) where __U: ::core::default::Default + ::core::iter::Extend, __F: ::core::ops::FnMut(&Self::Item) -> bool; // Once try_trait_v2 is stabilized, we can replace these by implementing try_rfold. #[inline] fn fold<__U, __F>(self, init: __U, f: __F) -> __U where __F: ::core::ops::FnMut(__U, Self::Item) -> __U; #[inline] fn all<__F>(&mut self, f: __F) -> bool where __F: ::core::ops::FnMut(Self::Item) -> bool; #[inline] fn any<__F>(&mut self, f: __F) -> bool where __F: ::core::ops::FnMut(Self::Item) -> bool; #[inline] fn find<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(&Self::Item) -> bool; #[inline] fn find_map<__U, __F>(&mut self, f: __F) -> ::core::option::Option<__U> where __F: ::core::ops::FnMut(Self::Item) -> ::core::option::Option<__U>; #[inline] fn position<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(Self::Item) -> bool; } })) } } pub(crate) mod double_ended_iterator { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["DoubleEndedIterator"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { // TODO: Add try_rfold once try_trait_v2 is stabilized https://github.com/rust-lang/rust/issues/84277 // TODO: Add advance_back_by once stabilized https://github.com/rust-lang/rust/issues/77404 Ok(derive_trait( data, &parse_quote!(::core::iter::DoubleEndedIterator), Some(format_ident!("Item")), parse_quote! { trait DoubleEndedIterator: ::core::iter::Iterator { #[inline] fn next_back(&mut self) -> ::core::option::Option; #[inline] fn nth_back(&mut self, n: usize) -> ::core::option::Option; // Once try_trait_v2 is stabilized, we can replace these by implementing try_rfold. #[inline] fn rfold<__U, __F>(self, init: __U, f: __F) -> __U where __F: ::core::ops::FnMut(__U, Self::Item) -> __U; #[inline] fn rfind<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(&Self::Item) -> bool; } }, )) } } pub(crate) mod exact_size_iterator { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["ExactSizeIterator"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { // TODO: Add is_empty once stabilized https://github.com/rust-lang/rust/issues/35428 Ok(derive_trait( data, &parse_quote!(::core::iter::ExactSizeIterator), Some(format_ident!("Item")), parse_quote! { trait ExactSizeIterator: ::core::iter::Iterator { #[inline] fn len(&self) -> usize; } }, )) } } pub(crate) mod fused_iterator { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["FusedIterator"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait( data, &parse_quote!(::core::iter::FusedIterator), Some(format_ident!("Item")), parse_quote! { trait FusedIterator: ::core::iter::Iterator {} }, )) } } #[cfg(feature = "trusted_len")] pub(crate) mod trusted_len { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["TrustedLen"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait( data, &parse_quote!(::core::iter::TrustedLen), Some(format_ident!("Item")), parse_quote! { unsafe trait TrustedLen: ::core::iter::Iterator {} }, )) } } pub(crate) mod extend { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["Extend"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { // TODO: Add extend_one,extend_reserve once stabilized https://github.com/rust-lang/rust/issues/72631 Ok(derive_trait(data, &parse_quote!(::core::iter::Extend), None, parse_quote! { trait Extend<__A> { #[inline] fn extend<__T: ::core::iter::IntoIterator>(&mut self, iter: __T); } })) } } auto_enums-0.8.7/src/derive/core/mod.rs000064400000000000000000000004171046102023000161430ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT /// `core::convert` #[cfg(feature = "convert")] pub(crate) mod convert; /// `core::fmt` pub(crate) mod fmt; /// `core::future` pub(crate) mod future; /// `core::iter` pub(crate) mod iter; /// `core::ops` pub(crate) mod ops; auto_enums-0.8.7/src/derive/core/ops.rs000064400000000000000000000152421046102023000161670ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT #[cfg(feature = "ops")] pub(crate) mod deref { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["Deref"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::core::ops::Deref), None, parse_quote! { trait Deref { type Target; #[inline] fn deref(&self) -> &Self::Target; } })) } } #[cfg(feature = "ops")] pub(crate) mod deref_mut { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["DerefMut"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait( data, &parse_quote!(::core::ops::DerefMut), Some(format_ident!("Target")), parse_quote! { trait DerefMut: ::core::ops::Deref { #[inline] fn deref_mut(&mut self) -> &mut Self::Target; } }, )) } } #[cfg(feature = "ops")] pub(crate) mod index { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["Index"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::core::ops::Index), None, parse_quote! { trait Index<__Idx> { type Output; #[inline] fn index(&self, index: __Idx) -> &Self::Output; } })) } } #[cfg(feature = "ops")] pub(crate) mod index_mut { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["IndexMut"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait( data, &parse_quote!(::core::ops::IndexMut), Some(format_ident!("Output")), parse_quote! { trait IndexMut<__Idx>: ::core::ops::Index<__Idx> { #[inline] fn index_mut(&mut self, index: __Idx) -> &mut Self::Output; } }, )) } } #[cfg(feature = "ops")] pub(crate) mod range_bounds { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["RangeBounds"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::core::ops::RangeBounds), None, parse_quote! { trait RangeBounds<__T: ?Sized> { #[inline] fn start_bound(&self) -> ::core::ops::Bound<&__T>; #[inline] fn end_bound(&self) -> ::core::ops::Bound<&__T>; } })) } } #[cfg(feature = "coroutine_trait")] pub(crate) mod coroutine { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["Coroutine"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::core::ops::Coroutine); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait Coroutine { type Yield; type Return; } }) .build_impl(); let resume = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::resume(#pin::new_unchecked(x), arg), } }); impl_.items.push(parse_quote! { #[inline] fn resume( self: #pin<&mut Self>, arg: R, ) -> ::core::ops::CoroutineState { unsafe { match self.get_unchecked_mut() { #(#resume)* } } } }); Ok(impl_.into_token_stream()) } } #[cfg(feature = "fn_traits")] pub(crate) mod fn_ { use syn::TypeParam; use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["Fn"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { let trait_path = quote!(::core::ops::Fn); let trait_ = quote!(#trait_path(__T) -> __U); let mut impl_ = EnumImpl::new(data); impl_.set_trait(parse_quote!(#trait_path<(__T,)>)); impl_.push_generic_param(TypeParam::from(format_ident!("__T")).into()); impl_.push_generic_param(TypeParam::from(format_ident!("__U")).into()); data.field_types().for_each(|f| impl_.push_where_predicate(parse_quote!(#f: #trait_))); impl_.push_method(parse_quote! { #[inline] extern "rust-call" fn call(&self, args: (__T,)) -> Self::Output; }); Ok(impl_.build()) } } #[cfg(feature = "fn_traits")] pub(crate) mod fn_mut { use syn::TypeParam; use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["FnMut"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { let trait_path = quote!(::core::ops::FnMut); let trait_ = quote!(#trait_path(__T) -> __U); let mut impl_ = EnumImpl::new(data); impl_.set_trait(parse_quote!(#trait_path<(__T,)>)); impl_.push_generic_param(TypeParam::from(format_ident!("__T")).into()); impl_.push_generic_param(TypeParam::from(format_ident!("__U")).into()); data.field_types().for_each(|f| impl_.push_where_predicate(parse_quote!(#f: #trait_))); impl_.push_method(parse_quote! { #[inline] extern "rust-call" fn call_mut(&mut self, args: (__T,)) -> Self::Output; }); Ok(impl_.build()) } } #[cfg(feature = "fn_traits")] pub(crate) mod fn_once { use syn::TypeParam; use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["FnOnce"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { let trait_path = quote!(::core::ops::FnOnce); let trait_ = quote!(#trait_path(__T) -> __U); let mut impl_ = EnumImpl::new(data); impl_.set_trait(parse_quote!(#trait_path<(__T,)>)); impl_.push_generic_param(TypeParam::from(format_ident!("__T")).into()); impl_.push_generic_param(TypeParam::from(format_ident!("__U")).into()); data.field_types().for_each(|f| impl_.push_where_predicate(parse_quote!(#f: #trait_))); impl_.append_items_from_trait(parse_quote! { trait FnOnce { type Output; #[inline] extern "rust-call" fn call_once(self, args: (__T,)) -> Self::Output; } }); Ok(impl_.build()) } } auto_enums-0.8.7/src/derive/external/futures01.rs000064400000000000000000000036611046102023000201200ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT pub(crate) mod future { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["futures01::Future"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::futures::future::Future), None, parse_quote! { trait Future { type Item; type Error; #[inline] fn poll(&mut self) -> ::futures::Poll; } })) } } pub(crate) mod stream { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["futures01::Stream"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::futures::stream::Stream), None, parse_quote! { trait Stream { type Item; type Error; #[inline] fn poll( &mut self, ) -> ::futures::Poll<::core::option::Option, Self::Error>; } })) } } pub(crate) mod sink { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["futures01::Sink"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::futures::sink::Sink), None, parse_quote! { trait Sink { type SinkItem; type SinkError; #[inline] fn start_send( &mut self, item: Self::SinkItem, ) -> ::futures::StartSend; #[inline] fn poll_complete(&mut self) -> ::futures::Poll<(), Self::SinkError>; #[inline] fn close(&mut self) -> ::futures::Poll<(), Self::SinkError>; } })) } } auto_enums-0.8.7/src/derive/external/futures03.rs000064400000000000000000000302771046102023000201250ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT pub(crate) mod async_buf_read { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["futures03::AsyncBufRead"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::futures::io::AsyncBufRead); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncBufRead {} }) .build_impl(); let poll_fill_buf = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_fill_buf(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { #[inline] fn poll_fill_buf( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<&[u8]>> { unsafe { match self.get_unchecked_mut() { #(#poll_fill_buf)* } } } }); let consume = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::consume(#pin::new_unchecked(x), amt), } }); impl_.items.push(parse_quote! { #[inline] fn consume(self: #pin<&mut Self>, amt: usize) { unsafe { match self.get_unchecked_mut() { #(#consume)* } } } }); Ok(impl_.into_token_stream()) } } pub(crate) mod async_read { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["futures03::AsyncRead"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::futures::io::AsyncRead); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncRead {} }) .build_impl(); let poll_read = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_read(#pin::new_unchecked(x), cx, buf), } }); impl_.items.push(parse_quote! { #[inline] fn poll_read( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, buf: &mut [u8], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { #(#poll_read)* } } } }); let poll_read_vectored = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_read_vectored(#pin::new_unchecked(x), cx, bufs), } }); impl_.items.push(parse_quote! { #[inline] fn poll_read_vectored( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, bufs: &mut [::std::io::IoSliceMut<'_>], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { #(#poll_read_vectored)* } } } }); Ok(impl_.into_token_stream()) } } pub(crate) mod async_seek { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["futures03::AsyncSeek"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::futures::io::AsyncSeek); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncSeek {} }) .build_impl(); let poll_seek = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_seek(#pin::new_unchecked(x), cx, pos), } }); impl_.items.push(parse_quote! { #[inline] fn poll_seek( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, pos: ::std::io::SeekFrom, ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { #(#poll_seek)* } } } }); Ok(impl_.into_token_stream()) } } pub(crate) mod async_write { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["futures03::AsyncWrite"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::futures::io::AsyncWrite); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncWrite {} }) .build_impl(); let poll_write = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_write(#pin::new_unchecked(x), cx, buf), } }); impl_.items.push(parse_quote! { #[inline] fn poll_write( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, buf: &[u8], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { #(#poll_write)* } } } }); let poll_write_vectored = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_write_vectored(#pin::new_unchecked(x), cx, bufs), } }); impl_.items.push(parse_quote! { #[inline] fn poll_write_vectored( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, bufs: &[::std::io::IoSlice<'_>], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { #(#poll_write_vectored)* } } } }); let poll_flush = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_flush(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { #[inline] fn poll_flush( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { #(#poll_flush)* } } } }); let poll_close = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_close(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { #[inline] fn poll_close( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { #(#poll_close)* } } } }); Ok(impl_.into_token_stream()) } } pub(crate) mod sink { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["futures03::Sink"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::futures::sink::Sink); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait Sink<__Item> { type Error; } }) .build_impl(); let poll_ready = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_<__Item>>::poll_ready(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { #[inline] fn poll_ready( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::core::result::Result<(), Self::Error>> { unsafe { match self.get_unchecked_mut() { #(#poll_ready)* } } } }); let start_send = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_<__Item>>::start_send(#pin::new_unchecked(x), item), } }); impl_.items.push(parse_quote! { #[inline] fn start_send( self: #pin<&mut Self>, item: __Item, ) -> ::core::result::Result<(), Self::Error> { unsafe { match self.get_unchecked_mut() { #(#start_send)* } } } }); let poll_flush = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_<__Item>>::poll_flush(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { #[inline] fn poll_flush( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::core::result::Result<(), Self::Error>> { unsafe { match self.get_unchecked_mut() { #(#poll_flush)* } } } }); let poll_close = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_<__Item>>::poll_close(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { #[inline] fn poll_close( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::core::result::Result<(), Self::Error>> { unsafe { match self.get_unchecked_mut() { #(#poll_close)* } } } }); Ok(impl_.into_token_stream()) } } pub(crate) mod stream { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["futures03::Stream"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::futures::stream::Stream); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait Stream { type Item; #[inline] fn size_hint(&self) -> (usize, ::core::option::Option); } }) .build_impl(); let poll_next = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_next(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { #[inline] fn poll_next( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::core::option::Option> { unsafe { match self.get_unchecked_mut() { #(#poll_next)* } } } }); Ok(impl_.into_token_stream()) } } auto_enums-0.8.7/src/derive/external/http_body1.rs000064400000000000000000000030221046102023000203260ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT pub(crate) mod body { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["http_body1::Body"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::http_body::Body); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait Body { type Data; type Error; #[inline] fn is_end_stream(&self) -> bool; #[inline] fn size_hint(&self) -> ::http_body::SizeHint; } }) .build_impl(); let poll_frame = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_frame(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { fn poll_frame( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll< ::core::option::Option< ::core::result::Result<::http_body::Frame, Self::Error>, >, > { unsafe { match self.get_unchecked_mut() { #(#poll_frame)* } } } }); Ok(impl_.into_token_stream()) } } auto_enums-0.8.7/src/derive/external/mod.rs000064400000000000000000000014141046102023000170330ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT // https://docs.rs/futures/0.1 #[cfg(feature = "futures01")] pub(crate) mod futures01; // https://docs.rs/futures/0.3 #[cfg(feature = "futures03")] pub(crate) mod futures03; // https://docs.rs/rayon/1 #[cfg(feature = "rayon")] pub(crate) mod rayon; // https://docs.rs/serde/1 #[cfg(feature = "serde")] pub(crate) mod serde; // https://docs.rs/tokio/0.1 #[cfg(feature = "tokio01")] pub(crate) mod tokio01; // https://docs.rs/tokio/0.2 #[cfg(feature = "tokio02")] pub(crate) mod tokio02; // https://docs.rs/tokio/0.3 #[cfg(feature = "tokio03")] pub(crate) mod tokio03; // https://docs.rs/tokio/1 #[cfg(feature = "tokio1")] pub(crate) mod tokio1; // https://docs.rs/http-body/1 #[cfg(feature = "http_body1")] pub(crate) mod http_body1; auto_enums-0.8.7/src/derive/external/rayon.rs000064400000000000000000000044611046102023000174110ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT pub(crate) mod par_iter { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["rayon::ParallelIterator"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::rayon::iter::ParallelIterator), None, parse_quote! { trait ParallelIterator { type Item; #[inline] fn drive_unindexed<__C>(self, consumer: __C) -> __C::Result where __C: ::rayon::iter::plumbing::UnindexedConsumer; #[inline] fn opt_len(&self) -> ::core::option::Option; } })) } } pub(crate) mod indexed_par_iter { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["rayon::IndexedParallelIterator"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait( data, &parse_quote!(::rayon::iter::IndexedParallelIterator), Some(format_ident!("Item")), parse_quote! { trait IndexedParallelIterator: ::rayon::iter::ParallelIterator { #[inline] fn drive<__C>(self, consumer: __C) -> __C::Result where __C: ::rayon::iter::plumbing::Consumer; #[inline] fn len(&self) -> usize; #[inline] fn with_producer<__CB>(self, callback: __CB) -> __CB::Output where __CB: ::rayon::iter::plumbing::ProducerCallback; } }, )) } } pub(crate) mod par_extend { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["rayon::ParallelExtend"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::rayon::iter::ParallelExtend), None, parse_quote! { trait ParallelExtend<__T: Send> { #[inline] fn par_extend<__I>(&mut self, par_iter: __I) where __I: ::rayon::iter::IntoParallelIterator; } })) } } auto_enums-0.8.7/src/derive/external/serde.rs000064400000000000000000000012331046102023000173550ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT pub(crate) mod serialize { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["serde::Serialize"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::serde::ser::Serialize), None, parse_quote! { trait Serialize { #[inline] fn serialize<__S>( &self, serializer: __S, ) -> ::core::result::Result<__S::Ok, __S::Error> where __S: ::serde::ser::Serializer; } })) } } auto_enums-0.8.7/src/derive/external/tokio01.rs000064400000000000000000000036331046102023000175470ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT pub(crate) mod async_read { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["tokio01::AsyncRead"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::tokio::io::AsyncRead), None, parse_quote! { trait AsyncRead: ::std::io::Read { unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool; fn poll_read( &mut self, buf: &mut [u8], ) -> ::tokio::prelude::Poll; // tokio01 seems does not reexport BufMut. // fn read_buf<__B: BufMut>( // &mut self, // buf: &mut __B, // ) -> ::tokio::prelude::Poll // where // Self: Sized; } })) } } pub(crate) mod async_write { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["tokio01::AsyncWrite"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::tokio::io::AsyncWrite), None, parse_quote! { trait AsyncWrite: ::std::io::Write { fn poll_write( &mut self, buf: &[u8], ) -> ::tokio::prelude::Poll; fn poll_flush(&mut self) -> ::tokio::prelude::Poll<(), ::std::io::Error>; fn shutdown(&mut self) -> ::tokio::prelude::Poll<(), ::std::io::Error>; // tokio01 seems does not reexport Buf. // fn write_buf<__B: Buf>(&mut self, buf: &mut __B) -> ::tokio::prelude::Poll // where // Self: Sized; } })) } } auto_enums-0.8.7/src/derive/external/tokio02.rs000064400000000000000000000173311046102023000175500ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT pub(crate) mod async_buf_read { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["tokio02::AsyncBufRead"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::tokio::io::AsyncBufRead); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncBufRead {} }) .build_impl(); let poll_fill_buf = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_fill_buf(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { fn poll_fill_buf( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<&[u8]>> { unsafe { match self.get_unchecked_mut() { #(#poll_fill_buf)* } } } }); let consume = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::consume(#pin::new_unchecked(x), amt), } }); impl_.items.push(parse_quote! { fn consume(self: #pin<&mut Self>, amt: usize) { unsafe { match self.get_unchecked_mut() { #(#consume)* } } } }); Ok(impl_.into_token_stream()) } } pub(crate) mod async_read { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["tokio02::AsyncRead"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::tokio::io::AsyncRead); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncRead { unsafe fn prepare_uninitialized_buffer( &self, buf: &mut [::core::mem::MaybeUninit], ) -> bool; } }) .build_impl(); let poll_read = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_read(#pin::new_unchecked(x), cx, buf), } }); impl_.items.push(parse_quote! { fn poll_read( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, buf: &mut [u8], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { #(#poll_read)* } } } }); // tokio02 seems does not reexport BufMut. // fn poll_read_buf<__B: BufMut>( // self: ::core::pin::Pin<&mut Self>, // cx: &mut ::core::task::Context<'_>, // buf: &mut __B, // ) -> ::core::task::Poll<::std::io::Result> // where // Self: Sized; Ok(impl_.into_token_stream()) } } pub(crate) mod async_seek { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["tokio02::AsyncSeek"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::tokio::io::AsyncSeek); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncSeek {} }) .build_impl(); let start_seek = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::start_seek(#pin::new_unchecked(x), cx, pos), } }); impl_.items.push(parse_quote! { fn start_seek( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, pos: ::std::io::SeekFrom, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { #(#start_seek)* } } } }); let poll_complete = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_complete(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { fn poll_complete( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { #(#poll_complete)* } } } }); Ok(impl_.into_token_stream()) } } pub(crate) mod async_write { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["tokio02::AsyncWrite"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::tokio::io::AsyncWrite); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncWrite {} }) .build_impl(); let poll_write = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_write(#pin::new_unchecked(x), cx, buf), } }); impl_.items.push(parse_quote! { fn poll_write( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, buf: &[u8], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { #(#poll_write)* } } } }); let poll_flush = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_flush(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { fn poll_flush( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { #(#poll_flush)* } } } }); let poll_shutdown = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_shutdown(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { fn poll_shutdown( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { #(#poll_shutdown)* } } } }); // tokio02 seems does not reexport Buf. // fn poll_write_buf<__B: Buf>( // self: ::core::pin::Pin<&mut Self>, // cx: &mut ::core::task::Context<'_>, // buf: &mut __B, // ) -> ::core::task::Poll<::std::io::Result> // where // Self: Sized; Ok(impl_.into_token_stream()) } } auto_enums-0.8.7/src/derive/external/tokio03.rs000064400000000000000000000155241046102023000175530ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT pub(crate) mod async_buf_read { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["tokio03::AsyncBufRead"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::tokio::io::AsyncBufRead); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncBufRead {} }) .build_impl(); let poll_fill_buf = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_fill_buf(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { fn poll_fill_buf( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<&[u8]>> { unsafe { match self.get_unchecked_mut() { #(#poll_fill_buf)* } } } }); let consume = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::consume(#pin::new_unchecked(x), amt), } }); impl_.items.push(parse_quote! { fn consume(self: #pin<&mut Self>, amt: usize) { unsafe { match self.get_unchecked_mut() { #(#consume)* } } } }); Ok(impl_.into_token_stream()) } } pub(crate) mod async_read { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["tokio03::AsyncRead"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::tokio::io::AsyncRead); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncRead {} }) .build_impl(); let poll_read = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_read(#pin::new_unchecked(x), cx, buf), } }); impl_.items.push(parse_quote! { fn poll_read( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, buf: &mut ::tokio::io::ReadBuf<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { #(#poll_read)* } } } }); Ok(impl_.into_token_stream()) } } pub(crate) mod async_seek { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["tokio03::AsyncSeek"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::tokio::io::AsyncSeek); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncSeek {} }) .build_impl(); let start_seek = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::start_seek(#pin::new_unchecked(x), pos), } }); impl_.items.push(parse_quote! { fn start_seek( self: #pin<&mut Self>, pos: ::std::io::SeekFrom, ) -> ::std::io::Result<()> { unsafe { match self.get_unchecked_mut() { #(#start_seek)* } } } }); let poll_complete = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_complete(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { fn poll_complete( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { #(#poll_complete)* } } } }); Ok(impl_.into_token_stream()) } } pub(crate) mod async_write { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["tokio03::AsyncWrite"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::tokio::io::AsyncWrite); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncWrite {} }) .build_impl(); let poll_write = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_write(#pin::new_unchecked(x), cx, buf), } }); impl_.items.push(parse_quote! { fn poll_write( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, buf: &[u8], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { #(#poll_write)* } } } }); let poll_flush = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_flush(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { fn poll_flush( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { #(#poll_flush)* } } } }); let poll_shutdown = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_shutdown(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { fn poll_shutdown( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { #(#poll_shutdown)* } } } }); Ok(impl_.into_token_stream()) } } auto_enums-0.8.7/src/derive/external/tokio1.rs000064400000000000000000000171151046102023000174670ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT pub(crate) mod async_buf_read { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["tokio1::AsyncBufRead"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::tokio::io::AsyncBufRead); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncBufRead {} }) .build_impl(); let poll_fill_buf = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_fill_buf(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { fn poll_fill_buf( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<&[u8]>> { unsafe { match self.get_unchecked_mut() { #(#poll_fill_buf)* } } } }); let consume = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::consume(#pin::new_unchecked(x), amt), } }); impl_.items.push(parse_quote! { fn consume(self: #pin<&mut Self>, amt: usize) { unsafe { match self.get_unchecked_mut() { #(#consume)* } } } }); Ok(impl_.into_token_stream()) } } pub(crate) mod async_read { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["tokio1::AsyncRead"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::tokio::io::AsyncRead); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncRead {} }) .build_impl(); let poll_read = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_read(#pin::new_unchecked(x), cx, buf), } }); impl_.items.push(parse_quote! { fn poll_read( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, buf: &mut ::tokio::io::ReadBuf<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { #(#poll_read)* } } } }); Ok(impl_.into_token_stream()) } } pub(crate) mod async_seek { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["tokio1::AsyncSeek"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::tokio::io::AsyncSeek); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncSeek {} }) .build_impl(); let start_seek = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::start_seek(#pin::new_unchecked(x), pos), } }); impl_.items.push(parse_quote! { fn start_seek( self: #pin<&mut Self>, pos: ::std::io::SeekFrom, ) -> ::std::io::Result<()> { unsafe { match self.get_unchecked_mut() { #(#start_seek)* } } } }); let poll_complete = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_complete(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { fn poll_complete( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { #(#poll_complete)* } } } }); Ok(impl_.into_token_stream()) } } pub(crate) mod async_write { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["tokio1::AsyncWrite"]; pub(crate) fn derive(cx: &Context, data: &Data) -> Result { cx.needs_pin_projection(); let ident = &data.ident; let pin = quote!(::core::pin::Pin); let trait_ = parse_quote!(::tokio::io::AsyncWrite); let mut impl_ = EnumImpl::from_trait(data, &trait_, None, parse_quote! { trait AsyncWrite { fn is_write_vectored(&self) -> bool; } }) .build_impl(); let poll_write = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_write(#pin::new_unchecked(x), cx, buf), } }); impl_.items.push(parse_quote! { fn poll_write( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, buf: &[u8], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { #(#poll_write)* } } } }); let poll_flush = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_flush(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { fn poll_flush( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { #(#poll_flush)* } } } }); let poll_shutdown = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_shutdown(#pin::new_unchecked(x), cx), } }); impl_.items.push(parse_quote! { fn poll_shutdown( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { #(#poll_shutdown)* } } } }); let poll_write_vectored = data.variant_idents().zip(data.field_types()).map(|(v, ty)| { quote! { #ident::#v(x) => <#ty as #trait_>::poll_write_vectored(#pin::new_unchecked(x), cx, bufs), } }); impl_.items.push(parse_quote! { fn poll_write_vectored( self: #pin<&mut Self>, cx: &mut ::core::task::Context<'_>, bufs: &[::std::io::IoSlice<'_>], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { #(#poll_write_vectored)* } } } }); Ok(impl_.into_token_stream()) } } auto_enums-0.8.7/src/derive/mod.rs000064400000000000000000000010041046102023000152040ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT #![allow(clippy::unnecessary_wraps)] pub(crate) mod core; pub(crate) mod external; #[cfg(feature = "std")] pub(crate) mod std; pub(crate) mod ty_impls; mod prelude { pub(super) use derive_utils::{derive_trait, EnumData as Data, EnumImpl}; pub(super) use proc_macro2::TokenStream; pub(super) use quote::{format_ident, quote, ToTokens as _}; pub(super) use syn::{parse_quote, Result}; pub(super) use crate::enum_derive::DeriveContext as Context; } auto_enums-0.8.7/src/derive/std/error.rs000064400000000000000000000016271046102023000163630ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["Error"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { let ident = &data.ident; let source = data.variant_idents().map(|v| quote!(#ident::#v(x) => ::std::option::Option::Some(x))); let source = parse_quote! { fn source(&self) -> ::std::option::Option<&(dyn (::std::error::Error) + 'static)> { match self { #(#source,)* } } }; let mut impl_ = EnumImpl::from_trait(data, &parse_quote!(::std::error::Error), None, parse_quote! { trait Error { #[allow(deprecated)] fn description(&self) -> &str; } }); data.field_types().for_each(|f| impl_.push_where_predicate(parse_quote!(#f: 'static))); impl_.push_item(source); Ok(impl_.build()) } auto_enums-0.8.7/src/derive/std/io.rs000064400000000000000000000076031046102023000156410ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT pub(crate) mod read { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["Read", "io::Read"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { // TODO: Add is_read_vectored once stabilized https://github.com/rust-lang/rust/issues/69941 // TODO: Add read_buf,read_buf_exact once stabilized https://github.com/rust-lang/rust/issues/78485 Ok(derive_trait(data, &parse_quote!(::std::io::Read), None, parse_quote! { trait Read { #[inline] fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result; #[inline] fn read_vectored( &mut self, bufs: &mut [::std::io::IoSliceMut<'_>], ) -> ::std::io::Result; #[inline] fn read_to_end( &mut self, buf: &mut ::std::vec::Vec, ) -> ::std::io::Result; #[inline] fn read_to_string( &mut self, buf: &mut ::std::string::String, ) -> ::std::io::Result; #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> ::std::io::Result<()>; } })) } } pub(crate) mod write { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["Write", "io::Write"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { // TODO: Add is_write_vectored once stabilized https://github.com/rust-lang/rust/issues/69941 // TODO: Add write_all_vectored once stabilized https://github.com/rust-lang/rust/issues/70436 Ok(derive_trait(data, &parse_quote!(::std::io::Write), None, parse_quote! { trait Write { #[inline] fn write(&mut self, buf: &[u8]) -> ::std::io::Result; #[inline] fn write_vectored( &mut self, bufs: &[::std::io::IoSlice<'_>], ) -> ::std::io::Result; #[inline] fn flush(&mut self) -> ::std::io::Result<()>; #[inline] fn write_all(&mut self, buf: &[u8]) -> ::std::io::Result<()>; #[inline] fn write_fmt( &mut self, fmt: ::std::fmt::Arguments<'_>, ) -> ::std::io::Result<()>; } })) } } pub(crate) mod seek { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["Seek", "io::Seek"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::std::io::Seek), None, parse_quote! { trait Seek { #[inline] fn seek(&mut self, pos: ::std::io::SeekFrom) -> ::std::io::Result; } })) } } pub(crate) mod buf_read { use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["BufRead", "io::BufRead"]; pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { Ok(derive_trait(data, &parse_quote!(::std::io::BufRead), None, parse_quote! { trait BufRead { #[inline] fn fill_buf(&mut self) -> ::std::io::Result<&[u8]>; #[inline] fn consume(&mut self, amt: usize); #[inline] fn read_until( &mut self, byte: u8, buf: &mut ::std::vec::Vec, ) -> ::std::io::Result; #[inline] fn read_line( &mut self, buf: &mut ::std::string::String, ) -> ::std::io::Result; } })) } } auto_enums-0.8.7/src/derive/std/mod.rs000064400000000000000000000001671046102023000160070ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT /// `std::error` pub(crate) mod error; /// `std::io` pub(crate) mod io; auto_enums-0.8.7/src/derive/ty_impls/mod.rs000064400000000000000000000001571046102023000170540ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT #[cfg(feature = "transpose_methods")] pub(crate) mod transpose; auto_enums-0.8.7/src/derive/ty_impls/transpose.rs000064400000000000000000000100631046102023000203100ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use syn::TypeParam; use crate::derive::prelude::*; pub(crate) const NAME: &[&str] = &["Transpose"]; // Implementing this with `Into` requires many type annotations. pub(crate) fn derive(_cx: &Context, data: &Data) -> Result { check_fields(data)?; let mut items = TokenStream::new(); items.extend(transpose_option(data)); items.extend(transpose_result(data)); items.extend(transpose_ok(data)); items.extend(transpose_err(data)); Ok(items) } fn check_fields(data: &Data) -> Result<()> { let generics = &data.generics; let fields = data.field_types(); let comma = if generics.params.empty_or_trailing() { quote!(,) } else { TokenStream::new() }; if quote!(#generics).to_string() == quote!(<#(#fields),*#comma>).to_string() { Ok(()) } else { bail!(data, "all fields need to be generics") } } fn transpose_option(data: &Data) -> TokenStream { let ident = &data.ident; let mut impl_ = EnumImpl::new(data); let transpose = data.variant_idents().map(|v| quote!(#ident::#v(x) => x.map(#ident::#v))); let fields = data.field_types(); impl_.push_item(parse_quote! { #[inline] fn transpose(self) -> ::core::option::Option<#ident<#(#fields),*>> { match self { #(#transpose,)* } } }); let mut impl_ = impl_.build_impl(); let ty_generics = data.field_types().map(|f| quote!(::core::option::Option<#f>)); impl_.self_ty = parse_quote!(#ident<#(#ty_generics),*>); impl_.into_token_stream() } fn transpose_result(data: &Data) -> TokenStream { let ident = &data.ident; let fields = data.field_types(); let mut impl_ = EnumImpl::new(data); let err_fields: Vec<_> = (0..fields.len()) .map(|i| { let id = format_ident!("__E{}", i); impl_.push_generic_param(TypeParam::from(id.clone()).into()); id }) .collect(); let transpose = data .variant_idents() .map(|v| quote!(#ident::#v(x) => x.map(#ident::#v).map_err(#ident::#v))); impl_.push_item(parse_quote! { #[inline] fn transpose( self, ) -> ::core::result::Result<#ident<#(#fields),*>, #ident<#(#err_fields),*>> { match self { #(#transpose,)* } } }); let mut impl_ = impl_.build_impl(); let ty_generics = data .field_types() .zip(err_fields.iter()) .map(|(f, ef)| quote!(::core::result::Result<#f, #ef>)); impl_.self_ty = parse_quote!(#ident<#(#ty_generics),*>); impl_.into_token_stream() } fn transpose_ok(data: &Data) -> TokenStream { let ident = &data.ident; let fields = data.field_types(); let mut impl_ = EnumImpl::new(data); impl_.push_generic_param(TypeParam::from(format_ident!("__E")).into()); let transpose = data.variant_idents().map(|v| quote!(#ident::#v(x) => x.map(#ident::#v))); impl_.push_item(parse_quote! { #[inline] fn transpose_ok(self) -> ::core::result::Result<#ident<#(#fields),*>, __E> { match self { #(#transpose,)* } } }); let mut impl_ = impl_.build_impl(); let ty_generics = data.field_types().map(|f| quote!(::core::result::Result<#f, __E>)); impl_.self_ty = parse_quote!(#ident<#(#ty_generics),*>); impl_.into_token_stream() } fn transpose_err(data: &Data) -> TokenStream { let ident = &data.ident; let fields = data.field_types(); let mut impl_ = EnumImpl::new(data); impl_.push_generic_param(TypeParam::from(format_ident!("__T")).into()); let transpose = data.variant_idents().map(|v| quote!(#ident::#v(x) => x.map_err(#ident::#v))); impl_.push_item(parse_quote! { #[inline] fn transpose_err(self) -> ::core::result::Result<__T, #ident<#(#fields),*>> { match self { #(#transpose,)* } } }); let mut impl_ = impl_.build_impl(); let ty_generics = data.field_types().map(|f| quote!(::core::result::Result<__T, #f>)); impl_.self_ty = parse_quote!(#ident<#(#ty_generics),*>); impl_.into_token_stream() } auto_enums-0.8.7/src/enum_derive.rs000064400000000000000000000261051046102023000154620ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use std::cell::Cell; use derive_utils::EnumData as Data; use proc_macro2::TokenStream; use quote::{quote, ToTokens as _}; use syn::{ parse::{Parse, ParseStream}, parse_quote, Error, ItemEnum, Path, Result, Token, }; pub(crate) fn attribute(args: TokenStream, input: TokenStream) -> TokenStream { expand(args, input).unwrap_or_else(Error::into_compile_error) } #[derive(Default)] pub(crate) struct DeriveContext { needs_pin_projection: Cell, } impl DeriveContext { pub(crate) fn needs_pin_projection(&self) { self.needs_pin_projection.set(true); } } type DeriveFn = fn(&'_ DeriveContext, &'_ Data) -> Result; fn get_derive(s: &str) -> Option { macro_rules! match_derive { ($($(#[$meta:meta])* $($arm:ident)::*,)*) => {$( $(#[$meta])* { if crate::derive::$($arm)::*::NAME.iter().any(|name| *name == s) { return Some(crate::derive::$($arm)::*::derive) } } )*}; } match_derive! { // core #[cfg(feature = "convert")] core::convert::as_mut, #[cfg(feature = "convert")] core::convert::as_ref, core::fmt::debug, core::fmt::display, #[cfg(feature = "fmt")] core::fmt::pointer, #[cfg(feature = "fmt")] core::fmt::binary, #[cfg(feature = "fmt")] core::fmt::octal, #[cfg(feature = "fmt")] core::fmt::upper_hex, #[cfg(feature = "fmt")] core::fmt::lower_hex, #[cfg(feature = "fmt")] core::fmt::upper_exp, #[cfg(feature = "fmt")] core::fmt::lower_exp, core::fmt::write, core::iter::iterator, core::iter::double_ended_iterator, core::iter::exact_size_iterator, core::iter::fused_iterator, #[cfg(feature = "trusted_len")] core::iter::trusted_len, core::iter::extend, #[cfg(feature = "ops")] core::ops::deref, #[cfg(feature = "ops")] core::ops::deref_mut, #[cfg(feature = "ops")] core::ops::index, #[cfg(feature = "ops")] core::ops::index_mut, #[cfg(feature = "ops")] core::ops::range_bounds, #[cfg(feature = "fn_traits")] core::ops::fn_, #[cfg(feature = "fn_traits")] core::ops::fn_mut, #[cfg(feature = "fn_traits")] core::ops::fn_once, #[cfg(feature = "coroutine_trait")] core::ops::coroutine, core::future, // std #[cfg(feature = "std")] std::io::read, #[cfg(feature = "std")] std::io::buf_read, #[cfg(feature = "std")] std::io::seek, #[cfg(feature = "std")] std::io::write, #[cfg(feature = "std")] std::error, // type impls #[cfg(feature = "transpose_methods")] ty_impls::transpose, // futures03 #[cfg(feature = "futures03")] external::futures03::stream, #[cfg(feature = "futures03")] external::futures03::sink, #[cfg(feature = "futures03")] external::futures03::async_read, #[cfg(feature = "futures03")] external::futures03::async_write, #[cfg(feature = "futures03")] external::futures03::async_seek, #[cfg(feature = "futures03")] external::futures03::async_buf_read, // futures01 #[cfg(feature = "futures01")] external::futures01::future, #[cfg(feature = "futures01")] external::futures01::stream, #[cfg(feature = "futures01")] external::futures01::sink, // rayon #[cfg(feature = "rayon")] external::rayon::par_iter, #[cfg(feature = "rayon")] external::rayon::indexed_par_iter, #[cfg(feature = "rayon")] external::rayon::par_extend, // serde #[cfg(feature = "serde")] external::serde::serialize, // tokio1 #[cfg(feature = "tokio1")] external::tokio1::async_read, #[cfg(feature = "tokio1")] external::tokio1::async_write, #[cfg(feature = "tokio1")] external::tokio1::async_seek, #[cfg(feature = "tokio1")] external::tokio1::async_buf_read, // tokio03 #[cfg(feature = "tokio03")] external::tokio03::async_read, #[cfg(feature = "tokio03")] external::tokio03::async_write, #[cfg(feature = "tokio03")] external::tokio03::async_seek, #[cfg(feature = "tokio03")] external::tokio03::async_buf_read, // tokio02 #[cfg(feature = "tokio02")] external::tokio02::async_read, #[cfg(feature = "tokio02")] external::tokio02::async_write, #[cfg(feature = "tokio02")] external::tokio02::async_seek, #[cfg(feature = "tokio02")] external::tokio02::async_buf_read, // tokio01 #[cfg(feature = "tokio01")] external::tokio01::async_read, #[cfg(feature = "tokio01")] external::tokio01::async_write, // http_body1 #[cfg(feature = "http_body1")] external::http_body1::body, } None } struct Args { inner: Vec<(String, Path)>, } impl Parse for Args { fn parse(input: ParseStream<'_>) -> Result { fn to_trimmed_string(p: &Path) -> String { p.to_token_stream().to_string().replace(' ', "") } let mut inner = vec![]; while !input.is_empty() { let path = input.parse()?; inner.push((to_trimmed_string(&path), path)); if input.is_empty() { break; } let _: Token![,] = input.parse()?; } Ok(Self { inner }) } } fn get_trait_deps(s: &str) -> Option<&'static [&'static str]> { Some(match s { "Copy" => &["Clone"], "Eq" | "PartialOrd" => &["PartialEq"], "Ord" => &["PartialOrd", "Eq", "PartialEq"], #[cfg(feature = "ops")] "DerefMut" => &["Deref"], #[cfg(feature = "ops")] "IndexMut" => &["Index"], #[cfg(feature = "fn_traits")] "Fn" => &["FnMut", "FnOnce"], #[cfg(feature = "fn_traits")] "FnMut" => &["FnOnce"], "DoubleEndedIterator" | "ExactSizeIterator" | "FusedIterator" => &["Iterator"], #[cfg(feature = "trusted_len")] "TrustedLen" => &["Iterator"], #[cfg(feature = "std")] "BufRead" | "io::BufRead" => &["Read"], #[cfg(feature = "std")] "Error" => &["Display", "Debug"], #[cfg(feature = "rayon")] "rayon::IndexedParallelIterator" => &["rayon::ParallelIterator"], _ => return None, }) } fn exists_alias(s: &str, v: &[(&str, Option<&Path>)]) -> bool { fn get_alias(s: &str) -> Option<&'static str> { macro_rules! match_alias { ($($(#[$meta:meta])* $($arm:ident)::*,)*) => {$( $(#[$meta])* { if s == crate::derive::$($arm)::*::NAME[0] { return Some(crate::derive::$($arm)::*::NAME[1]); } else if s == crate::derive::$($arm)::*::NAME[1] { return Some(crate::derive::$($arm)::*::NAME[0]); } } )*}; } match_alias! { // core core::fmt::debug, core::fmt::display, // std #[cfg(feature = "std")] std::io::read, #[cfg(feature = "std")] std::io::buf_read, #[cfg(feature = "std")] std::io::seek, #[cfg(feature = "std")] std::io::write, } None } get_alias(s).map_or(false, |x| v.iter().any(|(s, _)| *s == x)) } fn expand(args: TokenStream, input: TokenStream) -> Result { let data = syn::parse2::(input)?; let args = syn::parse2::(args)?.inner; let args = args.iter().fold(vec![], |mut v, (s, arg)| { if let Some(traits) = get_trait_deps(s) { for s in traits.iter().filter(|&x| !args.iter().any(|(s, _)| s == x)) { if !exists_alias(s, &v) { v.push((s, None)); } } } if !exists_alias(s, &v) { v.push((s, Some(arg))); } v }); let mut derive = vec![]; let mut items = TokenStream::new(); let cx = DeriveContext::default(); for (s, arg) in args { match (get_derive(s), arg) { (Some(f), _) => { items.extend( f(&cx, &data).map_err(|e| format_err!(data, "`enum_derive({})` {}", s, e))?, ); } (_, Some(arg)) => derive.push(arg), _ => {} } } let mut item = if cx.needs_pin_projection.get() { // If a user creates their own Unpin or Drop implementation, trait implementations with // `Pin<&mut self>` receiver can cause unsoundness. // // This was not a problem in #[auto_enum] attribute where enums are anonymized, // but it becomes a problem when users have access to enums (i.e., when using #[enum_derive]). // // So, we ensure safety here by an Unpin implementation that implements Unpin // only if all fields are Unpin (this also forbids custom Unpin implementation), // and a hack that forbids custom Drop implementation. (Both are what pin-project does by default.) // The repr(packed) check is not needed since repr(packed) is not available on enum. // Automatically create the appropriate conditional `Unpin` implementation. // https://github.com/taiki-e/pin-project/blob/v1.1.5/examples/struct-default-expanded.rs#L98 // TODO: use https://github.com/taiki-e/pin-project/issues/102#issuecomment-540472282's trick. // TODO: https://github.com/taiki-e/pin-project/pull/357 is also needed? items.extend(derive_utils::derive_trait( &data, &parse_quote!(::core::marker::Unpin), None, parse_quote! { trait Unpin {} }, )); let item: ItemEnum = data.into(); let name = &item.ident; let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl(); // Ensure that enum does not implement `Drop`. // https://github.com/taiki-e/pin-project/blob/v1.1.5/examples/struct-default-expanded.rs#L147 items.extend(quote! { const _: () = { trait MustNotImplDrop {} #[allow(clippy::drop_bounds, drop_bounds)] #[automatically_derived] impl MustNotImplDrop for T {} #[automatically_derived] impl #impl_generics MustNotImplDrop for #name #ty_generics #where_clause {} }; }); item } else { data.into() }; if !derive.is_empty() { item.attrs.push(parse_quote!(#[derive(#(#derive),*)])); } let mut item = item.into_token_stream(); item.extend(items); Ok(item) } auto_enums-0.8.7/src/error.rs000064400000000000000000000006171046102023000143110ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT macro_rules! format_err { ($span:expr, $msg:expr $(,)*) => { syn::Error::new_spanned(&$span as &dyn quote::ToTokens, &$msg as &dyn ::std::fmt::Display) }; ($span:expr, $($tt:tt)*) => { format_err!($span, format!($($tt)*)) }; } macro_rules! bail { ($($tt:tt)*) => { return Err(format_err!($($tt)*)) }; } auto_enums-0.8.7/src/lib.rs000064400000000000000000000774171046102023000137420ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT /*! A library for to allow multiple return types by automatically generated enum. This crate is a procedural macro implementation of the features discussions in [rust-lang/rfcs#2414]. This idea is also known as ["Anonymous sum types"][rust-lang/rfcs#294]. This library provides the following attribute macros: - `#[auto_enum]` Parses syntax, creates the enum, inserts variants, and passes specified traits to `#[enum_derive]`. - `#[enum_derive]` Implements specified traits to the enum. # `#[auto_enum]` `#[auto_enum]`'s basic feature is to wrap the value returned by the obvious branches (`match`, `if`, `return`, etc..) by an enum that implemented the specified traits. ```rust use auto_enums::auto_enum; #[auto_enum(Iterator)] fn foo(x: i32) -> impl Iterator { match x { 0 => 1..10, _ => vec![5, 10].into_iter(), } } ``` `#[auto_enum]` generates code in two stages. First, `#[auto_enum]` will do the following. - parses syntax - creates the enum - inserts variants Code like this will be generated: ```rust fn foo(x: i32) -> impl Iterator { #[::auto_enums::enum_derive(Iterator)] enum __Enum1<__T1, __T2> { __T1(__T1), __T2(__T2), } match x { 0 => __Enum1::__T1(1..10), _ => __Enum1::__T2(vec![5, 10].into_iter()), } } ``` Next, `#[enum_derive]` implements the specified traits.
Code like this will be generated: ```rust fn foo(x: i32) -> impl Iterator { enum __Enum1<__T1, __T2> { __T1(__T1), __T2(__T2), } impl<__T1, __T2> ::core::iter::Iterator for __Enum1<__T1, __T2> where __T1: ::core::iter::Iterator, __T2: ::core::iter::Iterator::Item>, { type Item = <__T1 as ::core::iter::Iterator>::Item; #[inline] fn next(&mut self) -> ::core::option::Option { match self { __Enum1::__T1(x) => x.next(), __Enum1::__T2(x) => x.next(), } } #[inline] fn size_hint(&self) -> (usize, ::core::option::Option) { match self { __Enum1::__T1(x) => x.size_hint(), __Enum1::__T2(x) => x.size_hint(), } } } match x { 0 => __Enum1::__T1(1..10), _ => __Enum1::__T2(vec![5, 10].into_iter()), } } ```

## Nested arms/branches `#[auto_enum]` can also parse nested arms/branches by using the `#[nested]` attribute. ```rust use auto_enums::auto_enum; #[auto_enum(Iterator)] fn foo(x: i32) -> impl Iterator { match x { 0 => 1..10, #[nested] _ => match x { 1 => vec![5, 10].into_iter(), _ => 0..=x, }, } } ``` `#[nested]` can be used basically in the same place as `#[auto_enum]`, except that `#[nested]` cannot be used in functions. ## Recursion If an error due to recursion occurs, you need to box branches where recursion occurs. ```rust use auto_enums::auto_enum; struct Type { child: Vec, } impl Type { #[auto_enum(Iterator)] fn method(&self) -> impl Iterator + '_ { if self.child.is_empty() { Some(()).into_iter() } else { // Boxing is only needed on branches where recursion occurs. Box::new(self.child.iter().flat_map(|c| c.method())) as Box> } } } ``` ## Positions where `#[auto_enum]` can be used. `#[auto_enum]` can be used in the following three places. However, since [stmt_expr_attributes] and [proc_macro_hygiene] are not stabilized, you need to use empty `#[auto_enum]` for functions except nightly. [stmt_expr_attributes]: https://github.com/rust-lang/rust/issues/15701 [proc_macro_hygiene]: https://github.com/rust-lang/rust/issues/54727 - functions ```rust use auto_enums::auto_enum; #[auto_enum(Iterator)] fn func(x: i32) -> impl Iterator { if x == 0 { Some(0).into_iter() } else { 0..x } } ``` - expressions ```rust use auto_enums::auto_enum; #[auto_enum] // Nightly does not need an empty attribute to the function. fn expr(x: i32) -> impl Iterator { #[auto_enum(Iterator)] match x { 0 => Some(0).into_iter(), _ => 0..x, } } ``` - let binding ```rust use auto_enums::auto_enum; #[auto_enum] // Nightly does not need an empty attribute to the function. fn let_binding(x: i32) -> impl Iterator { #[auto_enum(Iterator)] let iter = match x { 0 => Some(0).into_iter(), _ => 0..x, }; iter } ``` ## Supported syntax - `if` and `match` Wrap each branch with a variant. ```rust use auto_enums::auto_enum; // if #[auto_enum(Iterator)] fn expr_if(x: i32) -> impl Iterator { if x == 0 { Some(0).into_iter() } else { 0..x } } // match #[auto_enum] // Nightly does not need an empty attribute to the function. fn expr_match(x: i32) -> impl Iterator { #[auto_enum(Iterator)] let iter = match x { 0 => Some(0).into_iter(), _ => 0..x, }; iter } ``` - `loop` Wrap each `break` with a variant. Nested loops and labeled `break` are also supported. ```rust use auto_enums::auto_enum; #[auto_enum(Iterator)] fn expr_loop(mut x: i32) -> impl Iterator { loop { if x < 0 { break x..0; } else if x % 5 == 0 { break 0..=x; } x -= 1; } } ``` - `return` (in functions) `#[auto_enum]` can parse the `return` in the scope. This analysis is valid only when the return type is `impl Trait`. ```rust use auto_enums::auto_enum; // return (in functions) #[auto_enum(Iterator)] fn func(x: i32) -> impl Iterator { if x == 0 { return Some(0).into_iter(); } if x > 0 { 0..x } else { x..=0 } } ``` - `return` (in closures) `#[auto_enum]` can parse the `return` in the scope. This analysis is valid only when the following two conditions are satisfied. - `#[auto_enum]` must be used directly for that closure (or the let binding of the closure). - `?` operator not used in the scope. ```rust use auto_enums::auto_enum; // return (in closures) #[auto_enum] // Nightly does not need an empty attribute to the function. fn closure() -> impl Iterator { #[auto_enum(Iterator)] let f = |x| { if x == 0 { return Some(0).into_iter(); } if x > 0 { 0..x } else { x..=0 } }; f(1) } ``` - `?` operator (in functions) `#[auto_enum]` can parse the `?` operator in the scope. This analysis is valid only when the return type is `Result`. ```rust use auto_enums::auto_enum; use std::fmt::{Debug, Display}; // `?` operator (in functions) #[auto_enum(Debug, Display)] fn func(x: i32) -> Result { if x == 0 { Err("`x` is zero")?; } // The last branch of the function is not parsed. if x < 0 { Err(x)? } else { Ok(x + 1) } } ``` `?` operator is expanded as follows: ```rust # enum Enum { Variant(A) } # fn dox(expr: Result) -> Result> { # Ok( match expr { Ok(val) => val, Err(err) => return Err(Enum::Variant(err)), } # ) # } ``` - `?` operator (in closures) `#[auto_enum]` can parse the `?` operator in the scope. However, `#[auto_enum]` must be used directly for that closure (or the let binding of the closure). ```rust use auto_enums::auto_enum; use std::fmt::{Debug, Display}; // `?` operator (in closures) #[auto_enum] // Nightly does not need an empty attribute to the function. fn closure() -> Result { #[auto_enum(Debug, Display)] let f = |x| { if x == 0 { Err("`x` is zero")? } // The last branch of the function is not interpreted as a branch. if x < 0 { Err(x)? } else { Ok(x + 1) } }; f(1) } ``` - Block, unsafe block, method call, parentheses, and type ascription The following expressions are recursively searched until an `if`, `match`, `loop` or unsupported expression is found. - blocks - unsafe blocks - method calls - parentheses - type ascriptions ```rust use auto_enums::auto_enum; // block #[auto_enum] // Nightly does not need an empty attribute to the function. fn expr_block(x: i32) -> impl Iterator { #[auto_enum(Iterator)] { if x == 0 { Some(0).into_iter() } else { 0..x } } } // method call #[auto_enum] // Nightly does not need an empty attribute to the function. fn expr_method(x: i32) -> impl Iterator { #[auto_enum(Iterator)] match x { 0 => Some(0).into_iter(), _ => 0..x, }.map(|y| y + 1) } // parentheses # #[allow(unused_parens)] #[auto_enum(Iterator)] fn expr_parentheses(x: i32) -> impl Iterator { (if x == 0 { Some(0).into_iter() } else { 0..x }) } ``` ## Expression that no value will be returned If the last expression of a branch is one of the following, it is interpreted that no value will be returned (variant assignment is skipped). - `panic!(..)` - `unreachable!(..)` - `return` - `break` - `continue` - `None?` - `Err(..)?` - Expression level marker (`marker!` macro). - An item definition. Also, if the branch contains `#[nested]`, it is interpreted as returning an anonymous enum generated by `#[auto_enum]`, not a value. ```rust use auto_enums::auto_enum; #[auto_enum(Iterator)] fn foo(x: i32) -> impl Iterator { match x { 0 => 1..10, 1 => panic!(), // variant assignment is skipped _ => vec![5, 10].into_iter(), } } ``` You can also skip that branch explicitly by `#[never]` attribute. ```rust use auto_enums::auto_enum; #[auto_enum(Iterator)] fn foo(x: i32) -> impl Iterator { match x { 0 => 1..10, #[never] 1 => loop { panic!() }, _ => vec![5, 10].into_iter(), } } ``` ## Expression level marker (`marker!` macro) `#[auto_enum]` replaces `marker!` macros with variants. If values of two or more are specified by `marker!` macros, `#[auto_enum]` can be used for unsupported expressions and statements. ```rust use auto_enums::auto_enum; #[auto_enum(Iterator)] fn foo(x: i32) -> impl Iterator { if x < 0 { return x..=0; } marker!(1..10) } ``` The default name of the macro is `"marker"`, but you can change it by `marker` option. ```rust use auto_enums::auto_enum; #[auto_enum(marker = bar, Iterator)] fn foo(x: i32) -> impl Iterator { if x < 0 { return x..=0; } bar!(1..10) } ``` ## Rust Nightly When using `#[auto_enum]` for expressions and statements, `#[auto_enum]` for function is unnecessary. ```rust // Add this to your crate root: #![feature(proc_macro_hygiene, stmt_expr_attributes)] ``` ```rust # #![feature(proc_macro_hygiene, stmt_expr_attributes)] use auto_enums::auto_enum; fn foo(x: i32) -> i32 { #[auto_enum(Iterator)] let iter = match x { 0 => 1..10, _ => vec![5, 10].into_iter(), }; iter.fold(0, |sum, x| sum + x) } ``` You can also return closures. ```rust // Add this to your crate root: #![feature(fn_traits, unboxed_closures)] ``` ```rust # #![feature(fn_traits, unboxed_closures)] use auto_enums::auto_enum; #[auto_enum(Fn)] fn foo(x: bool) -> impl Fn(i32) -> i32 { if x { |y| y + 1 } else { |z| z - 1 } } ``` # `#[enum_derive]` `#[enum_derive]` implements the supported traits and passes unsupported traits to `#[derive]`. If you want to use traits that are not supported by `#[enum_derive]`, you can use another crate that provides [derives macros][proc-macro-derive], or you can define derives macros yourself ([derive_utils] probably can help it). Basic usage of `#[enum_derive]` ```rust use auto_enums::enum_derive; // `#[enum_derive]` implements `Iterator`, and `#[derive]` implements `Clone`. #[enum_derive(Iterator, Clone)] enum Foo { A(A), B(B), } ``` `#[enum_derive]` adds the dependency of the specified trait if it is not specified. ```rust use auto_enums::enum_derive; // `#[enum_derive]` implements `Iterator` and `ExactSizeIterator`. #[enum_derive(ExactSizeIterator)] enum Foo { A(A), B(B), } ``` [derive_utils]: https://github.com/taiki-e/derive_utils # Supported traits Some traits support is disabled by default. Note that some traits have aliases. *When using features that depend on unstable APIs, the `unstable` feature must be explicitly enabled* ## The standard library (`std`, `core`) ### `[std|core]::iter` - [`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) - [`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) - [`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) - [`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) - [`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) - [`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) *See also [iter-enum] crate.* ### `[std|core]::future` - [`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) ### `std::io` *(requires `"std"` crate feature)* - [`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) - [`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) - [`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) - [`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) *See also [io-enum] crate.* ### `[std|core]::ops` - [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) *(requires `"ops"` crate feature)* - [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html) *(requires `"ops"` crate feature)* - [`Index`](https://doc.rust-lang.org/std/ops/trait.Index.html) *(requires `"ops"` crate feature)* - [`IndexMut`](https://doc.rust-lang.org/std/ops/trait.IndexMut.html) *(requires `"ops"` crate feature)* - [`RangeBounds`](https://doc.rust-lang.org/std/ops/trait.RangeBounds.html) *(requires `"ops"` crate feature)* - [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html) *(requires `"fn_traits"` and `"unstable"` crate features)* - [`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html) *(requires `"fn_traits"` and `"unstable"` crate features)* - [`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) *(requires `"fn_traits"` and `"unstable"` crate features)* - [`Coroutine`](https://doc.rust-lang.org/nightly/std/ops/trait.Coroutine.html) *(requires `"coroutine_trait"` and `"unstable"` crate features)* ### `[std|core]::convert` - [`AsRef`](https://doc.rust-lang.org/std/convert/trait.AsRef.html) *(requires `"convert"` crate feature)* - [`AsMut`](https://doc.rust-lang.org/std/convert/trait.AsMut.html) *(requires `"convert"` crate feature)* ### `[std|core]::fmt` - [`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) - [`Display`](https://doc.rust-lang.org/std/fmt/trait.Display.html) (alias: `fmt::Display`) - [`fmt::Binary`](https://doc.rust-lang.org/std/fmt/trait.Binary.html) *(requires `"fmt"` crate feature)* - [`fmt::LowerExp`](https://doc.rust-lang.org/std/fmt/trait.LowerExp.html) *(requires `"fmt"` crate feature)* - [`fmt::LowerHex`](https://doc.rust-lang.org/std/fmt/trait.LowerHex.html) *(requires `"fmt"` crate feature)* - [`fmt::Octal`](https://doc.rust-lang.org/std/fmt/trait.Octal.html) *(requires `"fmt"` crate feature)* - [`fmt::Pointer`](https://doc.rust-lang.org/std/fmt/trait.Pointer.html) *(requires `"fmt"` crate feature)* - [`fmt::UpperExp`](https://doc.rust-lang.org/std/fmt/trait.UpperExp.html) *(requires `"fmt"` crate feature)* - [`fmt::UpperHex`](https://doc.rust-lang.org/std/fmt/trait.UpperHex.html) *(requires `"fmt"` crate feature)* - [`fmt::Write`](https://doc.rust-lang.org/std/fmt/trait.Write.html) ### `std::error` *(requires `"std"` crate feature)* - [`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) ## External libraries You can use support for external library traits by activating each crate feature. To use support for external library traits, you need to use the path starting with the feature name. For example: ```rust # extern crate rayon_crate as rayon; use auto_enums::auto_enum; use rayon::prelude::*; #[auto_enum(rayon::ParallelIterator)] // Note that this is not `#[auto_enum(ParallelIterator)]` fn func(x: i32) -> impl ParallelIterator { match x { 0 => (1..10).into_par_iter(), _ => vec![5, 10].into_par_iter(), } } ``` ### [futures v0.3][futures03] *(requires `"futures03"` crate feature)* - [`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) - [`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) - [`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) - [`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) - [`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) - [`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) ### [futures v0.1][futures01] *(requires `"futures01"` crate feature)* - [`futures01::Future`](https://docs.rs/futures/0.1/futures/future/trait.Future.html) - [`futures01::Stream`](https://docs.rs/futures/0.1/futures/stream/trait.Stream.html) - [`futures01::Sink`](https://docs.rs/futures/0.1/futures/sink/trait.Sink.html) ### [rayon] *(requires `"rayon"` crate feature)* - [`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) - [`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) - [`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) ### [serde] *(requires `"serde"` crate feature)* - [`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) ### [tokio v1][tokio1] *(requires `"tokio1"` crate feature)* - [`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) - [`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) - [`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) - [`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) ### [tokio v0.3][tokio03] *(requires `"tokio03"` crate feature)* - [`tokio03::AsyncRead`](https://docs.rs/tokio/0.3/tokio/io/trait.AsyncRead.html) - [`tokio03::AsyncWrite`](https://docs.rs/tokio/0.3/tokio/io/trait.AsyncWrite.html) - [`tokio03::AsyncSeek`](https://docs.rs/tokio/0.3/tokio/io/trait.AsyncSeek.html) - [`tokio03::AsyncBufRead`](https://docs.rs/tokio/0.3/tokio/io/trait.AsyncBufRead.html) ### [tokio v0.2][tokio02] *(requires `"tokio02"` crate feature)* - [`tokio02::AsyncRead`](https://docs.rs/tokio/0.2/tokio/io/trait.AsyncRead.html) - [`tokio02::AsyncWrite`](https://docs.rs/tokio/0.2/tokio/io/trait.AsyncWrite.html) - [`tokio02::AsyncSeek`](https://docs.rs/tokio/0.2/tokio/io/trait.AsyncSeek.html) - [`tokio02::AsyncBufRead`](https://docs.rs/tokio/0.2/tokio/io/trait.AsyncBufRead.html) ### [tokio v0.1][tokio01] *(requires `"tokio01"` crate feature)* - [`tokio01::AsyncRead`](https://docs.rs/tokio/0.1/tokio/io/trait.AsyncRead.html) - [`tokio01::AsyncWrite`](https://docs.rs/tokio/0.1/tokio/io/trait.AsyncWrite.html) ### [http_body v1][http_body1] *(requires `"http_body1"` crate feature)* - [`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) ## Inherent methods These don't derive traits, but derive inherent methods instead. - `Transpose` *(requires `"transpose_methods"` crate feature)* - this derives the following conversion methods. - `transpose` — convert from `enum,..>` to `Option>` - `transpose` — convert from `enum,..>` to `Result, enum>` - `transpose_ok` — convert from `enum,..>` to `Option, E>` Examples: ```rust use auto_enums::auto_enum; use std::{fs::File, io, path::Path}; #[auto_enum(Transpose, Write)] fn output_stream(file: Option<&Path>) -> io::Result { match file { Some(f) => File::create(f), None => Ok(io::stdout()), }.transpose_ok() } ``` - `transpose_err` — convert from `enum,..>` to `Result>` # Optional features - **`std`** *(enabled by default)* - Enable to use `std` library's traits. - **`ops`** - Enable to use `[std|core]::ops`'s `Deref`, `DerefMut`, `Index`, `IndexMut`, and `RangeBounds` traits. - **`convert`** - Enable to use `[std|core]::convert`'s `AsRef` and `AsMut` traits. - **`fmt`** - Enable to use `[std|core]::fmt`'s traits other than `Debug`, `Display` and `Write`. - **`transpose_methods`** - Enable to use `transpose*` methods. - **`futures03`** - Enable to use [futures v0.3][futures03] traits. - **`futures01`** - Enable to use [futures v0.1][futures01] traits. - **`rayon`** - Enable to use [rayon] traits. - **`serde`** - Enable to use [serde] traits. - **`tokio1`** - Enable to use [tokio v1][tokio1] traits. - **`tokio03`** - Enable to use [tokio v0.3][tokio03] traits. - **`tokio02`** - Enable to use [tokio v0.2][tokio02] traits. - **`tokio01`** - Enable to use [tokio v0.1][tokio01] traits. - **`http_body1`** - Enable to use [http_body v1][http_body1] traits. - **`coroutine_trait`** - Enable to use `[std|core]::ops::Coroutine` trait. - Note that this feature is unstable and may cause incompatible changes between patch versions. - **`fn_traits`** - Enable to use `[std|core]::ops`'s `Fn`, `FnMut`, and `FnOnce` traits. - Note that this feature is unstable and may cause incompatible changes between patch versions. - **`trusted_len`** - Enable to use `[std|core]::iter::TrustedLen` trait. - Note that this feature is unstable and may cause incompatible changes between patch versions. ## `type_analysis` feature Analyze return type of function and `let` binding. *Note that this feature is still experimental.* Examples: ```rust use auto_enums::auto_enum; #[auto_enum] // there is no need to specify std library's traits fn func1(x: i32) -> impl Iterator { match x { 0 => 1..10, _ => vec![5, 10].into_iter(), } } #[auto_enum] fn func2(x: i32) { // Unlike `feature(impl_trait_in_bindings)`, this works on stable compilers. #[auto_enum] let iter: impl Iterator = match x { 0 => Some(0).into_iter(), _ => 0..x, }; } ``` Please be careful if you return another traits with the same name. # Known limitations - There needs to explicitly specify the trait to be implemented (`type_analysis` crate feature reduces this limitation). - There needs to be marker macros for unsupported expressions. ## Related Projects - [derive_utils]: A procedural macro helper for easily writing [derives macros][proc-macro-derive] for enums. - [io-enum]: \#\[derive(Read, Write, Seek, BufRead)\] for enums. - [iter-enum]: \#\[derive(Iterator, DoubleEndedIterator, ExactSizeIterator, Extend)\] for enums. [derive_utils]: https://github.com/taiki-e/derive_utils [futures01]: https://docs.rs/futures/0.1 [futures03]: https://docs.rs/futures/0.3 [io-enum]: https://github.com/taiki-e/io-enum [iter-enum]: https://github.com/taiki-e/iter-enum [proc-macro-derive]: https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros [rayon]: https://docs.rs/rayon/1 [rust-lang/rfcs#294]: https://github.com/rust-lang/rfcs/issues/294 [rust-lang/rfcs#2414]: https://github.com/rust-lang/rfcs/issues/2414 [serde]: https://docs.rs/serde/1 [tokio01]: https://docs.rs/tokio/0.1 [tokio02]: https://docs.rs/tokio/0.2 [tokio03]: https://docs.rs/tokio/0.3 [tokio1]: https://docs.rs/tokio/1 [http_body1]: https://docs.rs/http-body/1 */ #![doc(test( no_crate_inject, attr( deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code, unused_variables) ) ))] #![forbid(unsafe_code)] #![allow(clippy::doc_link_with_quotes)] #[cfg(all(feature = "coroutine_trait", not(feature = "unstable")))] compile_error!( "The `coroutine_trait` feature requires the `unstable` feature as an explicit opt-in to unstable features" ); #[cfg(all(feature = "fn_traits", not(feature = "unstable")))] compile_error!( "The `fn_traits` feature requires the `unstable` feature as an explicit opt-in to unstable features" ); #[cfg(all(feature = "trusted_len", not(feature = "unstable")))] compile_error!( "The `trusted_len` feature requires the `unstable` feature as an explicit opt-in to unstable features" ); #[cfg(doctest)] #[doc = include_str!("../README.md")] const _README: () = (); #[macro_use] mod error; mod auto_enum; mod derive; mod enum_derive; mod utils; use proc_macro::TokenStream; /// An attribute macro like a wrapper of `#[derive]`, implementing /// the supported traits and passing unsupported traits to `#[derive]`. /// /// See crate level documentation for details. #[proc_macro_attribute] pub fn enum_derive(args: TokenStream, input: TokenStream) -> TokenStream { crate::enum_derive::attribute(args.into(), input.into()).into() } /// An attribute macro for to allow multiple return types by automatically generated enum. /// /// See crate level documentation for details. #[proc_macro_attribute] pub fn auto_enum(args: TokenStream, input: TokenStream) -> TokenStream { crate::auto_enum::attribute(args.into(), input.into()).into() } auto_enums-0.8.7/src/utils.rs000064400000000000000000000157431046102023000143260ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use std::{iter, mem}; use proc_macro2::TokenStream; use syn::{ punctuated::Punctuated, token, visit_mut::VisitMut, Arm, Attribute, Block, Expr, ExprBlock, ExprCall, ExprPath, ExprTuple, ItemFn, Local, Meta, Path, PathSegment, Stmt, StmtMacro, }; pub(crate) fn path(segments: impl IntoIterator) -> Path { Path { leading_colon: None, segments: segments.into_iter().collect() } } pub(crate) fn block(stmts: Vec) -> Block { Block { brace_token: token::Brace::default(), stmts } } pub(crate) fn expr_block(block: Block) -> Expr { Expr::Block(ExprBlock { attrs: vec![], label: None, block }) } pub(crate) fn expr_call(attrs: Vec, path: Path, arg: Expr) -> Expr { Expr::Call(ExprCall { attrs, func: Box::new(Expr::Path(ExprPath { attrs: vec![], qself: None, path })), paren_token: token::Paren::default(), args: iter::once(arg).collect(), }) } pub(crate) fn unit() -> Expr { Expr::Tuple(ExprTuple { attrs: vec![], paren_token: token::Paren::default(), elems: Punctuated::new(), }) } pub(crate) fn replace_expr(this: &mut Expr, f: impl FnOnce(Expr) -> Expr) { *this = f(mem::replace(this, Expr::Verbatim(TokenStream::new()))); } pub(crate) fn replace_block(this: &mut Block, f: impl FnOnce(Block) -> Expr) { // `brace_token` of the block that passed to `f` should have `call_site` span. // If `f` generates unused braces containing the span of `this.brace_token`, // this will cause confusing warnings: https://github.com/rust-lang/rust/issues/71080 let stmts = mem::take(&mut this.stmts); this.stmts = vec![Stmt::Expr(f(block(stmts)), None)]; } pub(crate) fn path_eq(path: &syn::Path, expected_crates: &[&str], expected_path: &[&str]) -> bool { if path.segments.len() == 1 && path.segments[0].ident == expected_path.last().unwrap() { return true; } if path.segments.len() == expected_path.len() + 1 { if !expected_crates.iter().any(|&c| path.segments[0].ident == c) { return false; } for i in 1..path.segments.len() { if path.segments[i].ident != expected_path[i - 1] { return false; } } return true; } false } // ----------------------------------------------------------------------------- // extension traits pub(crate) trait VecExt { fn find_remove(&mut self, predicate: impl FnMut(&T) -> bool) -> Option; } impl VecExt for Vec { fn find_remove(&mut self, predicate: impl FnMut(&T) -> bool) -> Option { self.iter().position(predicate).map(|i| self.remove(i)) } } // ----------------------------------------------------------------------------- // node pub(crate) trait Node { fn visited(&mut self, visitor: &mut impl VisitMut); } impl Node for Stmt { fn visited(&mut self, visitor: &mut impl VisitMut) { visitor.visit_stmt_mut(self); } } impl Node for Local { fn visited(&mut self, visitor: &mut impl VisitMut) { visitor.visit_local_mut(self); } } impl Node for Expr { fn visited(&mut self, visitor: &mut impl VisitMut) { visitor.visit_expr_mut(self); } } impl Node for Arm { fn visited(&mut self, visitor: &mut impl VisitMut) { visitor.visit_arm_mut(self); } } impl Node for Block { fn visited(&mut self, visitor: &mut impl VisitMut) { visitor.visit_block_mut(self); } } impl Node for ItemFn { fn visited(&mut self, visitor: &mut impl VisitMut) { visitor.visit_item_fn_mut(self); } } // ----------------------------------------------------------------------------- // helper for handling attributes pub(crate) trait Attrs { fn attrs(&self) -> &[Attribute]; fn any_attr(&self, ident: &str) -> bool { self.attrs().iter().any(|attr| attr.path().is_ident(ident)) } fn any_empty_attr(&self, ident: &str) -> bool { self.attrs().iter().any(|attr| matches!(&attr.meta, Meta::Path(p) if p.is_ident(ident))) } fn attrs_mut(&mut self) -> Option<&mut Vec>; fn find_remove_attr(&mut self, ident: &str) -> Option { self.attrs_mut()?.find_remove(|attr| attr.path().is_ident(ident)) } } impl Attrs for Arm { fn attrs(&self) -> &[Attribute] { &self.attrs } fn attrs_mut(&mut self) -> Option<&mut Vec> { Some(&mut self.attrs) } } impl Attrs for Local { fn attrs(&self) -> &[Attribute] { &self.attrs } fn attrs_mut(&mut self) -> Option<&mut Vec> { Some(&mut self.attrs) } } impl Attrs for StmtMacro { fn attrs(&self) -> &[Attribute] { &self.attrs } fn attrs_mut(&mut self) -> Option<&mut Vec> { Some(&mut self.attrs) } } impl Attrs for Stmt { fn attrs(&self) -> &[Attribute] { match self { Stmt::Expr(expr, _) => expr.attrs(), Stmt::Local(local) => local.attrs(), Stmt::Macro(mac) => mac.attrs(), // Ignore nested items. Stmt::Item(_) => &[], } } fn attrs_mut(&mut self) -> Option<&mut Vec> { match self { Stmt::Expr(expr, _) => expr.attrs_mut(), Stmt::Local(local) => local.attrs_mut(), Stmt::Macro(mac) => mac.attrs_mut(), // Ignore nested items. Stmt::Item(_) => None, } } } macro_rules! attrs_impl { ($($Expr:ident($Struct:ident),)*) => { impl Attrs for Expr { fn attrs(&self) -> &[Attribute] { // #[cfg_attr(test, deny(non_exhaustive_omitted_patterns))] match self { $(Expr::$Expr(syn::$Struct { attrs, .. }))|* => &attrs, _ => &[], } } fn attrs_mut(&mut self) -> Option<&mut Vec> { // #[cfg_attr(test, deny(non_exhaustive_omitted_patterns))] match self { $(Expr::$Expr(syn::$Struct { attrs, .. }))|* => Some(attrs), _ => None, } } } }; } attrs_impl! { Array(ExprArray), Assign(ExprAssign), Async(ExprAsync), Await(ExprAwait), Binary(ExprBinary), Block(ExprBlock), Break(ExprBreak), Call(ExprCall), Cast(ExprCast), Closure(ExprClosure), Const(ExprConst), Continue(ExprContinue), Field(ExprField), ForLoop(ExprForLoop), Group(ExprGroup), If(ExprIf), Index(ExprIndex), Infer(ExprInfer), Let(ExprLet), Lit(ExprLit), Loop(ExprLoop), Macro(ExprMacro), Match(ExprMatch), MethodCall(ExprMethodCall), Paren(ExprParen), Path(ExprPath), Range(ExprRange), Reference(ExprReference), Repeat(ExprRepeat), Return(ExprReturn), Struct(ExprStruct), Try(ExprTry), TryBlock(ExprTryBlock), Tuple(ExprTuple), Unary(ExprUnary), Unsafe(ExprUnsafe), While(ExprWhile), Yield(ExprYield), } auto_enums-0.8.7/tests/auto_enum.rs000064400000000000000000000756771046102023000155510ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT #![cfg_attr( feature = "fn_traits", feature(proc_macro_hygiene, stmt_expr_attributes, type_ascription) )] #![cfg_attr(feature = "coroutine_trait", feature(coroutine_trait))] #![cfg_attr(feature = "fn_traits", feature(fn_traits, unboxed_closures))] #![cfg_attr(feature = "trusted_len", feature(trusted_len))] #![cfg_attr(not(feature = "std"), no_std)] #![allow( dead_code, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::items_after_statements, clippy::let_and_return, clippy::needless_return, clippy::never_loop, clippy::no_effect_underscore_binding, clippy::undocumented_unsafe_blocks, clippy::unnecessary_wraps )] use core::iter; use auto_enums::auto_enum; #[test] fn stable() { const ANS: &[i32] = &[28, 3]; #[auto_enum(Iterator)] fn match_(x: usize) -> impl Iterator { match x { 0 => 1..8, n if n > 3 => 2..=10, _ => (0..2).map(|x| x + 1), } } for (i, x) in ANS.iter().enumerate() { assert_eq!(match_(i).sum::(), *x); } // block + unsafe block + parentheses #[rustfmt::skip] #[allow(unused_parens, unused_braces, unused_unsafe)] #[auto_enum(Iterator)] fn block(x: usize) -> impl Iterator { {{({ unsafe {{({ unsafe { unsafe {{ match x { 0 => 1..8, n if n > 3 => 2..=10, _ => (0..2).map(|x| x + 1), } }}}})}}})}} } for (i, x) in ANS.iter().enumerate() { assert_eq!(block(i).sum::(), *x); } #[auto_enum(Iterator)] fn if_(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { 2..=10 } else { (0..2).map(|x| x + 1) } } for (i, x) in ANS.iter().enumerate() { assert_eq!(if_(i).sum::(), *x); } #[auto_enum(Iterator)] fn method_call(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { 2..=10 } else { (0..2).map(|x| x + 1) } .map(|x| x + 1) .map(|x| x - 1) } for (i, x) in ANS.iter().enumerate() { assert_eq!(method_call(i).sum::(), *x); } #[auto_enum(Iterator)] fn no_return(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => panic!(), _ => (0..2).map(|x| x + 1), } } for (i, x) in ANS.iter().enumerate() { assert_eq!(no_return(i).sum::(), *x); } #[auto_enum(Iterator)] fn no_return2(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => match x { 0 => panic!(), 1..=3 => panic!(), _ => unreachable!(), }, _ => (0..2).map(|x| x + 1), } } for (i, x) in ANS.iter().enumerate() { assert_eq!(no_return2(i).sum::(), *x); } #[auto_enum(Iterator)] fn no_return3(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => match x { 0 => panic!(), 1..=3 => (1..4).map(|x| x + 1), _ => unreachable!(), }, _ => (0..2).map(|x| x + 1), } } for (i, x) in ANS.iter().enumerate() { assert_eq!(no_return3(i).sum::(), *x); } #[auto_enum(Iterator)] fn no_return4(i: usize) -> impl Iterator { if i == 0 { 1..8 } else if i > 6 { panic!(); } else if i > 5 { std::panic!("5"); } else if i > 4 { core::panic!("4"); } else if i > 3 { unreachable!("3"); } else if i > 2 { std::unreachable!("2"); } else if i > 1 { core::unreachable!(); } else { (0..2).map(|x| x + 1) } } for (i, x) in ANS.iter().enumerate() { assert_eq!(no_return4(i).sum::(), *x); } #[auto_enum(fmt::Debug)] fn no_return5(x: usize) -> impl core::fmt::Debug { match x { 0 => 1..8, 3 => {} _ => 0..=2, } } #[auto_enum(Iterator)] fn return1(x: usize) -> impl Iterator { if x > 10 { return (0..x as i32).map(|x| x - 1); } if x == 0 { 1..8 } else if x > 3 { 2..=10 } else { (0..2).map(|x| x + 1) } } for (i, x) in ANS.iter().enumerate() { assert_eq!(return1(i).sum::(), *x); } #[auto_enum(Iterator)] fn break_in_loop(mut x: i32) -> impl Iterator { loop { if x < 0 { break x..0; } else if x % 5 == 0 { break 0..=x; } x -= 1; } } assert_eq!(break_in_loop(14).sum::(), 55); assert_eq!(break_in_loop(-5).sum::(), -15); #[auto_enum(Iterator)] fn break2(mut x: i32) -> impl Iterator { 'a: loop { if x < 0 { break 'a x..0; } else if x % 5 == 0 { break 0..=x; } x -= 1; } } assert_eq!(break2(14).sum::(), 55); assert_eq!(break2(-5).sum::(), -15); #[auto_enum(Iterator)] fn break3(mut x: i32) -> impl Iterator { 'a: loop { if x < 0 { loop { break 'a x..0; } } else if x % 5 == 0 { return loop { break 0..=x; }; } x -= 1; } } assert_eq!(break3(14).sum::(), 55); assert_eq!(break3(-5).sum::(), -15); #[auto_enum(Iterator)] fn return_in_loop(mut x: i32) -> impl Iterator { loop { if x < 0 { return x..0; } else if x % 5 == 0 { return 0..=x; } x -= 1; } } assert_eq!(return_in_loop(14).sum::(), 55); assert_eq!(return_in_loop(-5).sum::(), -15); #[auto_enum(Iterator)] fn return2(x: i32, y: i32) -> impl Iterator { #[auto_enum(Iterator)] let iter = match x { 0 => 2..8, _ if y < 0 => return y..=0, _ => 2..=10, }; match y { 0 => iter.flat_map(|x| 0..x), _ => iter.map(|x| x + 1), } } assert_eq!(return2(10, 10).sum::(), 63); #[auto_enum] fn return3(x: i32) -> Option> { if x < 0 { return None; } #[auto_enum(Iterator)] let iter = match x { 0 => 2..8, 1 => None?, 2 => std::option::Option::None?, 3 => core::option::Option::None?, 4 => None::<_>?, _ => 2..=10, }; Some(iter) } assert_eq!(return3(10).unwrap().sum::(), 54); #[auto_enum] fn return4(x: i32) -> Result, ()> { if x < 0 { return Err(()); } #[auto_enum(Iterator)] let iter = match x { 0 => 2..8, 1 => Err(())?, 2 => std::result::Result::Err(())?, 3 => core::result::Result::Err(())?, 4 => Err::<_, ()>(())?, _ => 2..=10, }; Ok(iter) } assert_eq!(return4(10).unwrap().sum::(), 54); #[auto_enum(Debug, Display)] fn try_operator1(x: i32) -> Result, impl core::fmt::Debug> { if x < 0 { Err(1_i32)?; } let iter = match x { 0 => Err(())?, _ => 2..=10, }; Ok(iter) } assert_eq!(try_operator1(10).unwrap().sum::(), 54); #[auto_enum(Debug)] fn try_operator2( x: i32, ) -> std::result::Result, impl core::fmt::Debug> { if x < 0 { Err(1_i32)?; } match x { 0 => Err(())?, _ => Ok(2..=10), } } assert_eq!(try_operator2(10).unwrap().sum::(), 54); #[auto_enum(Debug)] fn try_operator3( x: i32, ) -> core::result::Result, impl core::fmt::Debug> { if x < 0 { Err(1_i32)?; } match x { 0 => Err(())?, _ => Ok(2..=10), } } assert_eq!(try_operator3(10).unwrap().sum::(), 54); #[auto_enum] fn closure() { #[auto_enum(Iterator)] let f = |x| { if x > 10 { return (0..x as i32).map(|x| x - 1); } if x == 0 { 1..8 } else if x > 3 { 2..=10 } else { (0..2).map(|x| x + 1) } }; for (i, x) in ANS.iter().enumerate() { assert_eq!(f(i).sum::(), *x); } let f = { #[auto_enum(Iterator)] |x| { if x > 10 { return (0..x as i32).map(|x| x - 1); } if x == 0 { 1..8 } else if x > 3 { 2..=10 } else { (0..2).map(|x| { return x + 1; }) } } }; for (i, x) in ANS.iter().enumerate() { assert_eq!(f(i).sum::(), *x); } } closure(); #[cfg(feature = "transpose_methods")] #[auto_enum(Transpose, Iterator, Clone)] fn transpose(x: isize) -> Option + Clone> { match x { 0 => Some(1..8), _ if x < 0 => return None, _ => Some(0..=10), } .transpose() .map(|i| i.map(|x| x + 1).map(|x| x - 1)) } #[cfg(feature = "transpose_methods")] assert_eq!(transpose(0).unwrap().sum::(), 28); } #[test] fn marker() { #[auto_enum(Iterator)] fn marker3(x: i32, y: i32) -> impl Iterator { let iter; // if #[auto_enum] is used on Stmt::Semi, #[auto_enum] does not visit last expr #[auto_enum(Iterator)] match x { 0 => iter = marker!(2..8), _ => iter = marker!(2..=10), }; if y < 0 { return y..=0; } match y { 0 => iter.flat_map(|x| 0..x), _ => iter.map(|x| { if x < 0 { return x - 1; } x + 1 }), } } assert_eq!(marker3(10, 10).sum::(), 63); #[auto_enum(marker = marker_a, Iterator)] fn marker4(x: i32, y: i32) -> impl Iterator { let iter; #[auto_enum(Iterator)] match x { 0 => iter = marker!(2..8), _ if y < 0 => return y..=0, _ => iter = marker!(2..=10), }; match y { 0 => iter.flat_map(|x| 0..x), _ => iter.map(|x| x + 1), } } assert_eq!(marker4(10, 10).sum::(), 63); #[auto_enum(Iterator)] fn marker5(x: i32, y: i32) -> impl Iterator { let iter; #[auto_enum(marker = marker_a, Iterator)] match x { 0 => iter = marker_a!(2..8), _ if y < 0 => return y..=0, _ => iter = marker_a!(2..=10), }; match y { 0 => iter.flat_map(|x| 0..x), _ => iter.map(|x| x + 1), } } assert_eq!(marker5(10, 10).sum::(), 63); #[auto_enum(Iterator, marker = foo)] fn marker6(x: usize) -> impl Iterator { #[auto_enum(Iterator)] let _iter = match x { 0 => 1..8, _ => (0..2).map(|x| x + 1), }; #[auto_enum(Iterator, marker = bar)] let _iter = match x { 0 => 1..8, 1 => return foo!(1..9), n if n > 3 => { #[auto_enum(Iterator, marker = baz)] match x { 0 => 1..8, 1 => return foo!(1..9), 2 => baz!(1..9), n if n > 3 => 2..=10, _ => (0..2).map(|x| x + 1), } } _ => (0..2).map(|x| x + 1), }; match x { 0 => 1..8, _ => (0..2).map(|x| x + 1), } } assert_eq!(marker6(10).sum::(), 3); } #[cfg(feature = "transpose_methods")] #[cfg(feature = "std")] #[test] fn stable_std() { use std::{error::Error, fs::File, io, path::Path}; use auto_enums::enum_derive; #[auto_enum(Transpose, Write)] fn transpose_ok(file: Option<&Path>) -> io::Result { if let Some(file) = file { File::create(file) } else { Ok(io::stdout()) }.transpose_ok() } assert!(transpose_ok(None).is_ok()); #[auto_enum(Transpose, Write)] fn transpose_option(file: Option<&Path>) -> Option { if let Some(file) = file { File::create(file).ok() } else { Some(io::stdout()) }.transpose() } assert!(transpose_option(None).is_some()); #[enum_derive(Debug, Display, Error)] enum IoError { Io(io::Error), Io2(io::Error), } #[auto_enum(Transpose, Write, Debug, Display, Error)] fn transpose_result(file: Option<&Path>) -> Result { if let Some(file) = file { File::create(file).map_err(IoError::Io) } else { let out: Result = Ok(io::stdout()); out } .transpose() } assert!(transpose_result(None).is_ok()); #[auto_enum(Transpose, Debug, Display, Error)] fn transpose_err(file: Option<&Path>) -> Result<(), impl Error> { if let Some(_f) = file { Err(IoError::Io2(io::Error::from(io::ErrorKind::NotFound))) } else { Err(io::Error::from(io::ErrorKind::NotFound)) } .transpose_err() } assert!(transpose_err(None).unwrap_err().source().is_some()); #[auto_enum(Debug, Display, Error)] fn try_operator(file: Option<&Path>) -> Result<(), impl Error> { if let Some(_f) = file { Err(IoError::Io2(io::Error::from(io::ErrorKind::NotFound)))?; } else { Err(io::Error::from(io::ErrorKind::NotFound))?; } Ok(()) } assert!(try_operator(None).unwrap_err().source().is_some()); } #[auto_enum] fn if_attr(x: bool) -> impl Iterator { let res = { #[auto_enum(Iterator)] if x { iter::once(0) } else { iter::repeat(1) } }; res } #[auto_enum(Iterator)] fn if_attr_in_if(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { #[nested] if x > 4 { 2..=10 } else { (11..20).map(|x| x - 1) } } else { (0..2).map(|x| x + 1) } } #[auto_enum] fn non_stmt_expr_match1(x: bool) -> Option> { Some( #[auto_enum(Iterator)] match x { true => iter::once(0), _ => iter::repeat(1), }, ) } #[auto_enum] fn non_stmt_expr_match2(x: bool) -> Option> { Some({ #[auto_enum(Iterator)] match x { true => iter::once(0), _ => iter::repeat(1), } }) } #[auto_enum] fn non_stmt_expr_match3(x: bool) { loop { let _ = { #[auto_enum(Iterator)] match x { true => iter::once(0), _ => iter::repeat(1), } }; break; } } #[auto_enum] fn non_stmt_expr_if(x: bool) -> Option> { Some( #[auto_enum(Iterator)] if x { iter::once(0) } else { iter::repeat(1) }, ) } #[test] fn nested() { #[auto_enum(Iterator)] fn match_in_match(x: usize) -> impl Iterator { match x { 0 => 1..8, #[nested] n if n > 3 => match x { 2..=10 => (1..x as i32).map(|x| x - 1), _ => 2..=10, }, _ => (0..2).map(|x| x + 1), } } for (i, x) in [28, 3].iter().enumerate() { assert_eq!(match_in_match(i).sum::(), *x); } #[auto_enum(Iterator)] fn match_in_match_nested(x: usize) -> impl Iterator { match x { 0 => 1..8, #[nested] n if n > 3 => match x { 2..=10 => { #[nested] match n { 4 => (1..x as i32).map(|x| x - 1), _ => (1..x as i32).map(|x| x + 1), } } _ => 2..=10, }, _ => (0..2).map(|x| x + 1), } } #[rustfmt::skip] #[allow(unused_braces, unused_unsafe)] #[auto_enum(Iterator)] fn in_block(x: usize) -> impl Iterator { {{{ unsafe {{{ unsafe { unsafe {{ match x { 0 => 1..8, #[nested] n if n > 3 => {{{ unsafe {{ if x > 10 { (-10..=x as i32).map(|x| x - 4) } else { (1..=4).map(|x| x - 4) } }}}}} _ => (0..2).map(|x| x + 1), } }}}}}}}}} } for (i, x) in [28, 3].iter().enumerate() { assert_eq!(in_block(i).sum::(), *x); } #[auto_enum(Iterator)] fn match_in_if(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { #[nested] match x { 1..=4 => 2..=10, _ => (11..20).map(|x| x - 1), } } else { (0..2).map(|x| x + 1) } } for (i, x) in [28, 3].iter().enumerate() { assert_eq!(match_in_if(i).sum::(), *x); } #[auto_enum(Iterator)] fn if_in_block_if(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { #[nested] { if x > 4 { 2..=10 } else { (11..20).map(|x| x - 1) } } } else { (0..2).map(|x| x + 1) } } for (i, x) in [28, 3].iter().enumerate() { assert_eq!(if_in_block_if(i).sum::(), *x); } #[auto_enum(Iterator)] fn match_in_let_match(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => { #[nested] let x = match x { 4..=10 => 2..=10, _ => (11..20).map(|x| x - 1), }; x } _ => (0..2).map(|x| x + 1), } } for (i, x) in [28, 3].iter().enumerate() { assert_eq!(match_in_let_match(i).sum::(), *x); } #[auto_enum(Iterator)] fn match_in_let_if(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => { #[nested] let x = if x > 4 { 2..=10 } else { (11..20).map(|x| x - 1) }; x } _ => (0..2).map(|x| x + 1), } } for (i, x) in [28, 3].iter().enumerate() { assert_eq!(match_in_let_if(i).sum::(), *x); } #[auto_enum(Iterator)] fn match_in_let_if_2(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => { #[nested] let x = if x > 4 { 2..=10 } else { #[nested] let x = match x { 4..=10 => 2..10, _ => (11..20).map(|x| x - 1), }; x }; x } _ => (0..2).map(|x| x + 1), } } #[auto_enum(Iterator)] fn if_in_let_if(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { #[nested] let x = if x > 4 { 2..=10 } else { (11..20).map(|x| x - 1) }; x } else { (0..2).map(|x| x + 1) } } for (i, x) in [28, 3].iter().enumerate() { assert_eq!(if_in_let_if(i).sum::(), *x); } #[auto_enum(Iterator)] fn if_in_let_if_nested(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { #[nested] let x = if x > 4 { #[nested] let x = if x > 4 { (2..=10).flat_map(|x| 1..x) } else { core::iter::empty() }; x } else { (11..20).map(|x| x - 1) }; x } else { (0..2).map(|x| x + 1) } } #[auto_enum(Iterator)] fn if_in_let_if_nested_nested(x: usize) -> impl Iterator { // 1 enum with 9 variants is generated. if x == 0 { 1..8 } else if x != 1 { #[nested] let x = if x > 5 { #[nested] let x = if x > 10 { #[nested] let x = if x > 11 { (2..=10).flat_map(|x| 1..x) } else { (11..20).map(|x| x - 1) }; x } else { #[nested] let x = if x > 9 { (2..=10).flat_map(|x| 1..x) } else { #[nested] let x = if x > 6 { #[nested] let x = if x > 7 { (2..=10).flat_map(|x| 1..x) } else { (11..20).map(|x| x - 1) }; x } else { (11..20).map(|x| x - 1) }; x }; x }; x } else { (11..20).map(|x| x - 1) }; x } else { (0..2).map(|x| x + 1) } } #[auto_enum(Iterator)] fn if_in_let_if_2(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { #[nested] let y = if x > 4 { 2..=10 } else { (11..20).map(|x| x - 1) }; #[nested] let z = if x < 4 { 2..10 } else { (11..20).map(|x| x - 1) }; if x > 5 { y } else { z } } else { (0..2).map(|x| x + 1) } } #[auto_enum(Iterator)] fn match_in_let_if_nop(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => { #[nested] let x = if x > 4 { 2..=10 } else { (11..20).map(|x| x - 1) }; #[nested] // no-op let _y = 111..120; x } _ => (0..2).map(|x| x + 1), } } #[auto_enum(Iterator)] fn if_in_let_if_nop(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { #[nested] let x = if x > 4 { 2..=10 } else { (11..20).map(|x| x - 1) }; #[nested] // no-op x } else { (0..2).map(|x| x + 1) } } #[auto_enum(Iterator)] fn match_nop(x: usize) -> impl Iterator { match x { 0 => 1..8, 3 => 2..=10, _ => (0..2).map(|x| x + 1), } } #[auto_enum(Iterator)] fn if_nop(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { 2..=10 } else { (0..2).map(|x| x + 1) } } #[auto_enum(Iterator)] fn no_return(x: usize) -> impl Iterator { match x { 0 => 1..8, #[nested] 3 => panic!(), _ => (0..2).map(|x| x + 1), } } } // nightly #[cfg(feature = "fn_traits")] mod nightly { use auto_enums::auto_enum; const ANS: &[i32] = &[28, 3]; #[test] fn nightly() { // let match for (i, x) in ANS.iter().enumerate() { #[auto_enum(Iterator)] let iter = match i { 0 => 1..8, _ => vec![1, 2, 0].into_iter(), }; assert_eq!(iter.sum::(), *x); } // let if for (i, x) in ANS.iter().enumerate() { #[auto_enum(Iterator)] let iter = if i == 0 { 1..8 } else if i > 3 { 1..=10 } else { vec![1, 2, 0].into_iter() }; assert_eq!(iter.sum::(), *x); } // no return for (i, x) in ANS.iter().enumerate() { #[auto_enum(Iterator)] let iter = match i { 0 => 1..8, #[never] 5..=10 => loop { panic!(); }, _ => vec![1, 2, 0].into_iter(), }; assert_eq!(iter.sum::(), *x); } for (i, x) in ANS.iter().enumerate() { #[auto_enum(Iterator)] let iter = match i { 0 => 1..8, 5..=10 => panic!(), 11..=20 => unreachable!(), 21..=30 => break, 31..=40 => continue, 41..=50 => return, _ => vec![1, 2, 0].into_iter(), }; assert_eq!(iter.sum::(), *x); } for (i, x) in ANS.iter().enumerate() { #[auto_enum(Iterator)] let iter = if i > 3 { #[never] loop { panic!(); } } else if i == 0 { 1..8 } else { vec![1, 2, 0].into_iter() }; assert_eq!(iter.sum::(), *x); } #[allow(clippy::needless_late_init)] fn assign(x: usize) -> impl Iterator + Clone { let a; a = #[auto_enum(Iterator, Clone)] match x { 0 => 2..8, _ if x < 2 => vec![2, 0].into_iter(), _ => 2..=10, }; a } for (i, x) in ANS.iter().enumerate() { assert_eq!(assign(i).sum::(), *x - 1); } /* This can not be supported. It is parsed as follows. expected: ExprAssign { left: ExprPath, right: ExprMatch, .. } found: ExprPath fn assign2(x: usize) -> impl Iterator + Clone { let a; #[auto_enum(Iterator, Clone)] a = match x { 0 => 2..8, _ if x < 2 => vec![2, 0].into_iter(), _ => 2..=10, }; a } */ #[auto_enum(Fn)] fn fn_traits1(option: bool) -> impl Fn(i32) -> i32 { if option { |x| x + 1 } else { |y| y - 1 } } assert_eq!(fn_traits1(true)(1), 2); #[auto_enum(Iterator, Clone)] let _y = match 0 { 0 => 2..8, _ => 2..=10, }; #[auto_enum(Iterator, Clone)] let _x = match 0 { 0 => 2..8, _ => 2..=10, }; } #[test] fn never() { // never attr for (i, x) in ANS.iter().enumerate() { #[auto_enum(Iterator)] let iter = match i { 0 => 1..8, #[never] 5..=10 => loop { panic!(); }, _ => match i { #[never] 5..=10 => loop { panic!(); }, #[never] 11..=20 => loop { panic!(); }, _ => vec![1, 2, 0].into_iter(), }, }; assert_eq!(iter.sum::(), *x); } for (i, x) in ANS.iter().enumerate() { #[rustfmt::skip] #[auto_enum(Iterator)] let iter = match i { 0 => 1..8, #[never] 5..=10 => loop { panic!(); }, 1..=4 => vec![1, 2, 0].into_iter(), _ => { match i { #[never] 5..=10 => loop { panic!(); }, #[never] 11..=20 => loop { panic!(); }, _ => panic!(), } } }; assert_eq!(iter.sum::(), *x); } } #[test] fn marker() { fn marker1(x: usize) -> impl Iterator + Clone { #[auto_enum(Iterator, Clone)] (0..x as i32).map(|x| x + 1).flat_map(|x| { if x > 10 { marker!(0..x) } else { marker!(-100..=0) } }) } for (i, _x) in ANS.iter().enumerate() { let _ = marker1(i).clone().sum::(); } fn marker2(x: usize) -> impl Iterator + Clone { let a; #[auto_enum(Iterator, Clone)] match x { 0 => a = marker!(2..8), _ if x < 2 => a = marker!(vec![2, 0].into_iter()), _ => a = marker!(2..=10), }; a } for (i, x) in ANS.iter().enumerate() { assert_eq!(marker2(i).clone().sum::(), *x - 1); } } #[test] fn non_stmt_expr() { // TODO: workaround rustc bug in the same way as https://github.com/taiki-e/futures-async-stream/pull/94. // use std::iter; // // fn match_(x: bool) -> Option> { // Some( // #[auto_enum(Iterator)] // match x { // true => iter::once(0), // _ => iter::repeat(1), // }, // ) // } // // fn if_(x: bool) -> Option> { // Some( // #[auto_enum(Iterator)] // if x { iter::once(0) } else { iter::repeat(1) }, // ) // } } } auto_enums-0.8.7/tests/compiletest.rs000064400000000000000000000011021046102023000160510ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT #![cfg(not(miri))] #![cfg(all( feature = "std", feature = "type_analysis", feature = "transpose_methods", feature = "futures01", feature = "futures03", feature = "rayon", feature = "serde", feature = "tokio01", feature = "tokio02", feature = "tokio03", feature = "tokio1", feature = "http_body1", ))] #[rustversion::attr(not(nightly), ignore)] #[test] fn ui() { let t = trybuild::TestCases::new(); t.compile_fail("tests/ui/**/*.rs"); t.pass("tests/run-pass/**/*.rs"); } auto_enums-0.8.7/tests/enum_derive.rs000064400000000000000000000050111046102023000160260ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT #![cfg_attr(feature = "coroutine_trait", feature(coroutine_trait))] #![cfg_attr(feature = "fn_traits", feature(fn_traits, unboxed_closures))] #![cfg_attr(feature = "trusted_len", feature(trusted_len))] #![allow(dead_code)] // See tests/run-pass for external crates. use auto_enums::enum_derive; #[test] fn not_formatted() { #[rustfmt::skip] #[enum_derive(Debug, Iterator)] enum Enum1 { A(A), B(B) } #[rustfmt::skip] #[enum_derive(Iterator)] enum Enum2<> { A(::core::ops::Range), B(::core::ops::RangeInclusive), } } #[test] fn stable() { #[enum_derive( Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, Extend, Debug, Display, fmt::Write, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Future )] enum Stable { A(A), B(B), } #[cfg(feature = "ops")] #[enum_derive(Deref, DerefMut, Index, IndexMut, RangeBounds)] enum Ops { A(A), B(B), } #[cfg(feature = "convert")] #[enum_derive(AsRef, AsMut)] enum Convert { A(A), B(B), } #[cfg(feature = "fmt")] #[enum_derive( fmt::Binary, fmt::LowerExp, fmt::LowerHex, fmt::Octal, fmt::Pointer, fmt::UpperExp, fmt::UpperHex )] enum Fmt { A(A), B(B), } #[cfg(feature = "transpose_methods")] #[enum_derive(Transpose)] enum Transpose { A(A), B(B), } #[enum_derive(Iterator, Clone)] #[enum_derive(Extend, Copy)] enum Enum3 { A(A), B(B), } } #[cfg(feature = "std")] #[test] fn stable_std() { #[enum_derive( BufRead, Read, Seek, Write, Display, Error, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash )] enum Stable { A(A), B(B), } } // nightly #[cfg(feature = "coroutine_trait")] #[test] fn coroutine_trait() { #[enum_derive(Coroutine)] enum Enum1 { A(A), B(B), } } #[cfg(feature = "fn_traits")] #[test] fn fn_traits() { #[enum_derive(Fn, FnMut, FnOnce)] enum Enum1 { A(A), B(B), } } #[cfg(feature = "trusted_len")] #[test] fn trusted_len() { #[enum_derive(TrustedLen)] enum Enum1 { A(A), B(B), } } auto_enums-0.8.7/tests/expand/.rustfmt.toml000064400000000000000000000000361046102023000171160ustar 00000000000000disable_all_formatting = true auto_enums-0.8.7/tests/expand/enum_derive/example-1.expanded.rs000064400000000000000000000123271046102023000226750ustar 00000000000000fn foo(x: i32) -> impl Iterator { enum __Enum1<__T1, __T2> { __T1(__T1), __T2(__T2), } #[automatically_derived] impl<__T1, __T2> ::core::iter::Iterator for __Enum1<__T1, __T2> where __T1: ::core::iter::Iterator, __T2: ::core::iter::Iterator::Item>, { type Item = <__T1 as ::core::iter::Iterator>::Item; #[inline] fn next(&mut self) -> ::core::option::Option { match self { __Enum1::__T1(x) => <__T1 as ::core::iter::Iterator>::next(x), __Enum1::__T2(x) => <__T2 as ::core::iter::Iterator>::next(x), } } #[inline] fn size_hint(&self) -> (usize, ::core::option::Option) { match self { __Enum1::__T1(x) => <__T1 as ::core::iter::Iterator>::size_hint(x), __Enum1::__T2(x) => <__T2 as ::core::iter::Iterator>::size_hint(x), } } #[inline] fn count(self) -> usize { match self { __Enum1::__T1(x) => <__T1 as ::core::iter::Iterator>::count(x), __Enum1::__T2(x) => <__T2 as ::core::iter::Iterator>::count(x), } } #[inline] fn last(self) -> ::core::option::Option { match self { __Enum1::__T1(x) => <__T1 as ::core::iter::Iterator>::last(x), __Enum1::__T2(x) => <__T2 as ::core::iter::Iterator>::last(x), } } #[inline] fn nth(&mut self, n: usize) -> ::core::option::Option { match self { __Enum1::__T1(x) => <__T1 as ::core::iter::Iterator>::nth(x, n), __Enum1::__T2(x) => <__T2 as ::core::iter::Iterator>::nth(x, n), } } #[inline] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] fn collect<__U: ::core::iter::FromIterator>(self) -> __U { match self { __Enum1::__T1(x) => <__T1 as ::core::iter::Iterator>::collect(x), __Enum1::__T2(x) => <__T2 as ::core::iter::Iterator>::collect(x), } } #[inline] fn partition<__U, __F>(self, f: __F) -> (__U, __U) where __U: ::core::default::Default + ::core::iter::Extend, __F: ::core::ops::FnMut(&Self::Item) -> bool, { match self { __Enum1::__T1(x) => <__T1 as ::core::iter::Iterator>::partition(x, f), __Enum1::__T2(x) => <__T2 as ::core::iter::Iterator>::partition(x, f), } } #[inline] fn fold<__U, __F>(self, init: __U, f: __F) -> __U where __F: ::core::ops::FnMut(__U, Self::Item) -> __U, { match self { __Enum1::__T1(x) => <__T1 as ::core::iter::Iterator>::fold(x, init, f), __Enum1::__T2(x) => <__T2 as ::core::iter::Iterator>::fold(x, init, f), } } #[inline] fn all<__F>(&mut self, f: __F) -> bool where __F: ::core::ops::FnMut(Self::Item) -> bool, { match self { __Enum1::__T1(x) => <__T1 as ::core::iter::Iterator>::all(x, f), __Enum1::__T2(x) => <__T2 as ::core::iter::Iterator>::all(x, f), } } #[inline] fn any<__F>(&mut self, f: __F) -> bool where __F: ::core::ops::FnMut(Self::Item) -> bool, { match self { __Enum1::__T1(x) => <__T1 as ::core::iter::Iterator>::any(x, f), __Enum1::__T2(x) => <__T2 as ::core::iter::Iterator>::any(x, f), } } #[inline] fn find<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(&Self::Item) -> bool, { match self { __Enum1::__T1(x) => <__T1 as ::core::iter::Iterator>::find(x, predicate), __Enum1::__T2(x) => <__T2 as ::core::iter::Iterator>::find(x, predicate), } } #[inline] fn find_map<__U, __F>(&mut self, f: __F) -> ::core::option::Option<__U> where __F: ::core::ops::FnMut(Self::Item) -> ::core::option::Option<__U>, { match self { __Enum1::__T1(x) => <__T1 as ::core::iter::Iterator>::find_map(x, f), __Enum1::__T2(x) => <__T2 as ::core::iter::Iterator>::find_map(x, f), } } #[inline] fn position<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(Self::Item) -> bool, { match self { __Enum1::__T1(x) => { <__T1 as ::core::iter::Iterator>::position(x, predicate) } __Enum1::__T2(x) => { <__T2 as ::core::iter::Iterator>::position(x, predicate) } } } } match x { 0 => __Enum1::__T1(1..10), _ => __Enum1::__T2(<[_]>::into_vec(::alloc::boxed::box_new([5, 10])).into_iter()), } } auto_enums-0.8.7/tests/expand/enum_derive/example-1.rs000064400000000000000000000005041046102023000211000ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT fn foo(x: i32) -> impl Iterator { #[::auto_enums::enum_derive(Iterator)] enum __Enum1<__T1, __T2> { __T1(__T1), __T2(__T2), } match x { 0 => __Enum1::__T1(1..10), _ => __Enum1::__T2(vec![5, 10].into_iter()), } } auto_enums-0.8.7/tests/expand/external/futures/async_buf_read.expanded.rs000064400000000000000000000037671046102023000250750ustar 00000000000000extern crate futures03_crate as futures; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::futures::io::AsyncBufRead for Enum where A: ::futures::io::AsyncBufRead, B: ::futures::io::AsyncBufRead, { #[inline] fn poll_fill_buf( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<&[u8]>> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_fill_buf( ::core::pin::Pin::new_unchecked(x), cx, ) } Enum::B(x) => { ::poll_fill_buf( ::core::pin::Pin::new_unchecked(x), cx, ) } } } } #[inline] fn consume(self: ::core::pin::Pin<&mut Self>, amt: usize) { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::consume( ::core::pin::Pin::new_unchecked(x), amt, ) } Enum::B(x) => { ::consume( ::core::pin::Pin::new_unchecked(x), amt, ) } } } } } #[automatically_derived] impl ::core::marker::Unpin for Enum where A: ::core::marker::Unpin, B: ::core::marker::Unpin, {} const _: () = { trait MustNotImplDrop {} #[allow(clippy::drop_bounds, drop_bounds)] #[automatically_derived] impl MustNotImplDrop for T {} #[automatically_derived] impl MustNotImplDrop for Enum {} }; fn main() {} auto_enums-0.8.7/tests/expand/external/futures/async_buf_read.rs000064400000000000000000000003251046102023000232710ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate futures03_crate as futures; use auto_enums::enum_derive; #[enum_derive(futures03::AsyncBufRead)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/external/futures/async_read.expanded.rs000064400000000000000000000044221046102023000242260ustar 00000000000000extern crate futures03_crate as futures; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::futures::io::AsyncRead for Enum where A: ::futures::io::AsyncRead, B: ::futures::io::AsyncRead, { #[inline] fn poll_read( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, buf: &mut [u8], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_read( ::core::pin::Pin::new_unchecked(x), cx, buf, ) } Enum::B(x) => { ::poll_read( ::core::pin::Pin::new_unchecked(x), cx, buf, ) } } } } #[inline] fn poll_read_vectored( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, bufs: &mut [::std::io::IoSliceMut<'_>], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_read_vectored( ::core::pin::Pin::new_unchecked(x), cx, bufs, ) } Enum::B(x) => { ::poll_read_vectored( ::core::pin::Pin::new_unchecked(x), cx, bufs, ) } } } } } #[automatically_derived] impl ::core::marker::Unpin for Enum where A: ::core::marker::Unpin, B: ::core::marker::Unpin, {} const _: () = { trait MustNotImplDrop {} #[allow(clippy::drop_bounds, drop_bounds)] #[automatically_derived] impl MustNotImplDrop for T {} #[automatically_derived] impl MustNotImplDrop for Enum {} }; fn main() {} auto_enums-0.8.7/tests/expand/external/futures/async_read.rs000064400000000000000000000003221046102023000224320ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate futures03_crate as futures; use auto_enums::enum_derive; #[enum_derive(futures03::AsyncRead)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/external/futures/async_seek.expanded.rs000064400000000000000000000027101046102023000242400ustar 00000000000000extern crate futures03_crate as futures; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::futures::io::AsyncSeek for Enum where A: ::futures::io::AsyncSeek, B: ::futures::io::AsyncSeek, { #[inline] fn poll_seek( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, pos: ::std::io::SeekFrom, ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_seek( ::core::pin::Pin::new_unchecked(x), cx, pos, ) } Enum::B(x) => { ::poll_seek( ::core::pin::Pin::new_unchecked(x), cx, pos, ) } } } } } #[automatically_derived] impl ::core::marker::Unpin for Enum where A: ::core::marker::Unpin, B: ::core::marker::Unpin, {} const _: () = { trait MustNotImplDrop {} #[allow(clippy::drop_bounds, drop_bounds)] #[automatically_derived] impl MustNotImplDrop for T {} #[automatically_derived] impl MustNotImplDrop for Enum {} }; fn main() {} auto_enums-0.8.7/tests/expand/external/futures/async_seek.rs000064400000000000000000000003221046102023000224460ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate futures03_crate as futures; use auto_enums::enum_derive; #[enum_derive(futures03::AsyncSeek)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/external/futures/async_write.expanded.rs000064400000000000000000000072561046102023000244550ustar 00000000000000extern crate futures03_crate as futures; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::futures::io::AsyncWrite for Enum where A: ::futures::io::AsyncWrite, B: ::futures::io::AsyncWrite, { #[inline] fn poll_write( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, buf: &[u8], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_write( ::core::pin::Pin::new_unchecked(x), cx, buf, ) } Enum::B(x) => { ::poll_write( ::core::pin::Pin::new_unchecked(x), cx, buf, ) } } } } #[inline] fn poll_write_vectored( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, bufs: &[::std::io::IoSlice<'_>], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_write_vectored( ::core::pin::Pin::new_unchecked(x), cx, bufs, ) } Enum::B(x) => { ::poll_write_vectored( ::core::pin::Pin::new_unchecked(x), cx, bufs, ) } } } } #[inline] fn poll_flush( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_flush( ::core::pin::Pin::new_unchecked(x), cx, ) } Enum::B(x) => { ::poll_flush( ::core::pin::Pin::new_unchecked(x), cx, ) } } } } #[inline] fn poll_close( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_close( ::core::pin::Pin::new_unchecked(x), cx, ) } Enum::B(x) => { ::poll_close( ::core::pin::Pin::new_unchecked(x), cx, ) } } } } } #[automatically_derived] impl ::core::marker::Unpin for Enum where A: ::core::marker::Unpin, B: ::core::marker::Unpin, {} const _: () = { trait MustNotImplDrop {} #[allow(clippy::drop_bounds, drop_bounds)] #[automatically_derived] impl MustNotImplDrop for T {} #[automatically_derived] impl MustNotImplDrop for Enum {} }; fn main() {} auto_enums-0.8.7/tests/expand/external/futures/async_write.rs000064400000000000000000000003231046102023000226520ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate futures03_crate as futures; use auto_enums::enum_derive; #[enum_derive(futures03::AsyncWrite)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/external/futures/sink.expanded.rs000064400000000000000000000067721046102023000230740ustar 00000000000000extern crate futures03_crate as futures; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::futures::sink::Sink<__Item> for Enum where A: ::futures::sink::Sink<__Item>, B: ::futures::sink::Sink< __Item, Error = >::Error, >, { type Error = >::Error; #[inline] fn poll_ready( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::core::result::Result<(), Self::Error>> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { >::poll_ready(::core::pin::Pin::new_unchecked(x), cx) } Enum::B(x) => { >::poll_ready(::core::pin::Pin::new_unchecked(x), cx) } } } } #[inline] fn start_send( self: ::core::pin::Pin<&mut Self>, item: __Item, ) -> ::core::result::Result<(), Self::Error> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { >::start_send(::core::pin::Pin::new_unchecked(x), item) } Enum::B(x) => { >::start_send(::core::pin::Pin::new_unchecked(x), item) } } } } #[inline] fn poll_flush( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::core::result::Result<(), Self::Error>> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { >::poll_flush(::core::pin::Pin::new_unchecked(x), cx) } Enum::B(x) => { >::poll_flush(::core::pin::Pin::new_unchecked(x), cx) } } } } #[inline] fn poll_close( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::core::result::Result<(), Self::Error>> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { >::poll_close(::core::pin::Pin::new_unchecked(x), cx) } Enum::B(x) => { >::poll_close(::core::pin::Pin::new_unchecked(x), cx) } } } } } #[automatically_derived] impl ::core::marker::Unpin for Enum where A: ::core::marker::Unpin, B: ::core::marker::Unpin, {} const _: () = { trait MustNotImplDrop {} #[allow(clippy::drop_bounds, drop_bounds)] #[automatically_derived] impl MustNotImplDrop for T {} #[automatically_derived] impl MustNotImplDrop for Enum {} }; fn main() {} auto_enums-0.8.7/tests/expand/external/futures/sink.rs000064400000000000000000000003151046102023000212700ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate futures03_crate as futures; use auto_enums::enum_derive; #[enum_derive(futures03::Sink)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/external/futures/stream.expanded.rs000064400000000000000000000033571046102023000234170ustar 00000000000000extern crate futures03_crate as futures; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::futures::stream::Stream for Enum where A: ::futures::stream::Stream, B: ::futures::stream::Stream::Item>, { type Item = ::Item; #[inline] fn size_hint(&self) -> (usize, ::core::option::Option) { match self { Enum::A(x) => ::size_hint(x), Enum::B(x) => ::size_hint(x), } } #[inline] fn poll_next( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::core::option::Option> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_next( ::core::pin::Pin::new_unchecked(x), cx, ) } Enum::B(x) => { ::poll_next( ::core::pin::Pin::new_unchecked(x), cx, ) } } } } } #[automatically_derived] impl ::core::marker::Unpin for Enum where A: ::core::marker::Unpin, B: ::core::marker::Unpin, {} const _: () = { trait MustNotImplDrop {} #[allow(clippy::drop_bounds, drop_bounds)] #[automatically_derived] impl MustNotImplDrop for T {} #[automatically_derived] impl MustNotImplDrop for Enum {} }; fn main() {} auto_enums-0.8.7/tests/expand/external/futures/stream.rs000064400000000000000000000003171046102023000216210ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate futures03_crate as futures; use auto_enums::enum_derive; #[enum_derive(futures03::Stream)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/external/http_body/body.expanded.rs000064400000000000000000000041041046102023000233470ustar 00000000000000extern crate http_body1_crate as http_body; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::http_body::Body for Enum where A: ::http_body::Body, B: ::http_body::Body< Data = ::Data, Error = ::Error, >, { type Data = ::Data; type Error = ::Error; #[inline] fn is_end_stream(&self) -> bool { match self { Enum::A(x) => ::is_end_stream(x), Enum::B(x) => ::is_end_stream(x), } } #[inline] fn size_hint(&self) -> ::http_body::SizeHint { match self { Enum::A(x) => ::size_hint(x), Enum::B(x) => ::size_hint(x), } } fn poll_frame( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll< ::core::option::Option< ::core::result::Result<::http_body::Frame, Self::Error>, >, > { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_frame( ::core::pin::Pin::new_unchecked(x), cx, ) } Enum::B(x) => { ::poll_frame( ::core::pin::Pin::new_unchecked(x), cx, ) } } } } } #[automatically_derived] impl ::core::marker::Unpin for Enum where A: ::core::marker::Unpin, B: ::core::marker::Unpin, {} const _: () = { trait MustNotImplDrop {} #[allow(clippy::drop_bounds, drop_bounds)] #[automatically_derived] impl MustNotImplDrop for T {} #[automatically_derived] impl MustNotImplDrop for Enum {} }; fn main() {} auto_enums-0.8.7/tests/expand/external/http_body/body.rs000064400000000000000000000003211046102023000215550ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate http_body1_crate as http_body; use auto_enums::enum_derive; #[enum_derive(http_body1::Body)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/external/rayon/indexed_parallel_iterator.expanded.rs000064400000000000000000000047501046102023000267620ustar 00000000000000extern crate rayon_crate as rayon; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::rayon::iter::ParallelIterator for Enum where A: ::rayon::iter::ParallelIterator, B: ::rayon::iter::ParallelIterator< Item = ::Item, >, { type Item = ::Item; #[inline] fn drive_unindexed<__C>(self, consumer: __C) -> __C::Result where __C: ::rayon::iter::plumbing::UnindexedConsumer, { match self { Enum::A(x) => { ::drive_unindexed(x, consumer) } Enum::B(x) => { ::drive_unindexed(x, consumer) } } } #[inline] fn opt_len(&self) -> ::core::option::Option { match self { Enum::A(x) => ::opt_len(x), Enum::B(x) => ::opt_len(x), } } } #[automatically_derived] impl ::rayon::iter::IndexedParallelIterator for Enum where A: ::rayon::iter::IndexedParallelIterator, B: ::rayon::iter::IndexedParallelIterator< Item = ::Item, >, { #[inline] fn drive<__C>(self, consumer: __C) -> __C::Result where __C: ::rayon::iter::plumbing::Consumer, { match self { Enum::A(x) => { ::drive(x, consumer) } Enum::B(x) => { ::drive(x, consumer) } } } #[inline] fn len(&self) -> usize { match self { Enum::A(x) => ::len(x), Enum::B(x) => ::len(x), } } #[inline] fn with_producer<__CB>(self, callback: __CB) -> __CB::Output where __CB: ::rayon::iter::plumbing::ProducerCallback, { match self { Enum::A(x) => { ::with_producer(x, callback) } Enum::B(x) => { ::with_producer(x, callback) } } } } fn main() {} auto_enums-0.8.7/tests/expand/external/rayon/indexed_parallel_iterator.rs000064400000000000000000000003261046102023000251660ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate rayon_crate as rayon; use auto_enums::enum_derive; #[enum_derive(rayon::IndexedParallelIterator)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/external/rayon/parallel_extend.expanded.rs000064400000000000000000000013421046102023000247120ustar 00000000000000extern crate rayon_crate as rayon; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::rayon::iter::ParallelExtend<__T> for Enum where A: ::rayon::iter::ParallelExtend<__T>, B: ::rayon::iter::ParallelExtend<__T>, { #[inline] fn par_extend<__I>(&mut self, par_iter: __I) where __I: ::rayon::iter::IntoParallelIterator, { match self { Enum::A(x) => { >::par_extend(x, par_iter) } Enum::B(x) => { >::par_extend(x, par_iter) } } } } fn main() {} auto_enums-0.8.7/tests/expand/external/rayon/parallel_extend.rs000064400000000000000000000003151046102023000231220ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate rayon_crate as rayon; use auto_enums::enum_derive; #[enum_derive(rayon::ParallelExtend)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/external/rayon/parallel_iterator.expanded.rs000064400000000000000000000021621046102023000252550ustar 00000000000000extern crate rayon_crate as rayon; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::rayon::iter::ParallelIterator for Enum where A: ::rayon::iter::ParallelIterator, B: ::rayon::iter::ParallelIterator< Item = ::Item, >, { type Item = ::Item; #[inline] fn drive_unindexed<__C>(self, consumer: __C) -> __C::Result where __C: ::rayon::iter::plumbing::UnindexedConsumer, { match self { Enum::A(x) => { ::drive_unindexed(x, consumer) } Enum::B(x) => { ::drive_unindexed(x, consumer) } } } #[inline] fn opt_len(&self) -> ::core::option::Option { match self { Enum::A(x) => ::opt_len(x), Enum::B(x) => ::opt_len(x), } } } fn main() {} auto_enums-0.8.7/tests/expand/external/rayon/parallel_iterator.rs000064400000000000000000000003171046102023000234660ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate rayon_crate as rayon; use auto_enums::enum_derive; #[enum_derive(rayon::ParallelIterator)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/external/serde/serialize.expanded.rs000064400000000000000000000012201046102023000235030ustar 00000000000000extern crate serde_crate as serde; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::serde::ser::Serialize for Enum where A: ::serde::ser::Serialize, B: ::serde::ser::Serialize, { #[inline] fn serialize<__S>( &self, serializer: __S, ) -> ::core::result::Result<__S::Ok, __S::Error> where __S: ::serde::ser::Serializer, { match self { Enum::A(x) => ::serialize(x, serializer), Enum::B(x) => ::serialize(x, serializer), } } } fn main() {} auto_enums-0.8.7/tests/expand/external/serde/serialize.rs000064400000000000000000000003101046102023000217130ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate serde_crate as serde; use auto_enums::enum_derive; #[enum_derive(serde::Serialize)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/external/tokio/async_buf_read.expanded.rs000064400000000000000000000037101046102023000245110ustar 00000000000000extern crate tokio1_crate as tokio; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::tokio::io::AsyncBufRead for Enum where A: ::tokio::io::AsyncBufRead, B: ::tokio::io::AsyncBufRead, { fn poll_fill_buf( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<&[u8]>> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_fill_buf( ::core::pin::Pin::new_unchecked(x), cx, ) } Enum::B(x) => { ::poll_fill_buf( ::core::pin::Pin::new_unchecked(x), cx, ) } } } } fn consume(self: ::core::pin::Pin<&mut Self>, amt: usize) { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::consume( ::core::pin::Pin::new_unchecked(x), amt, ) } Enum::B(x) => { ::consume( ::core::pin::Pin::new_unchecked(x), amt, ) } } } } } #[automatically_derived] impl ::core::marker::Unpin for Enum where A: ::core::marker::Unpin, B: ::core::marker::Unpin, {} const _: () = { trait MustNotImplDrop {} #[allow(clippy::drop_bounds, drop_bounds)] #[automatically_derived] impl MustNotImplDrop for T {} #[automatically_derived] impl MustNotImplDrop for Enum {} }; fn main() {} auto_enums-0.8.7/tests/expand/external/tokio/async_buf_read.rs000064400000000000000000000003151046102023000227200ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate tokio1_crate as tokio; use auto_enums::enum_derive; #[enum_derive(tokio1::AsyncBufRead)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/external/tokio/async_read.expanded.rs000064400000000000000000000026641046102023000236640ustar 00000000000000extern crate tokio1_crate as tokio; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::tokio::io::AsyncRead for Enum where A: ::tokio::io::AsyncRead, B: ::tokio::io::AsyncRead, { fn poll_read( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, buf: &mut ::tokio::io::ReadBuf<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_read( ::core::pin::Pin::new_unchecked(x), cx, buf, ) } Enum::B(x) => { ::poll_read( ::core::pin::Pin::new_unchecked(x), cx, buf, ) } } } } } #[automatically_derived] impl ::core::marker::Unpin for Enum where A: ::core::marker::Unpin, B: ::core::marker::Unpin, {} const _: () = { trait MustNotImplDrop {} #[allow(clippy::drop_bounds, drop_bounds)] #[automatically_derived] impl MustNotImplDrop for T {} #[automatically_derived] impl MustNotImplDrop for Enum {} }; fn main() {} auto_enums-0.8.7/tests/expand/external/tokio/async_read.rs000064400000000000000000000003121046102023000220610ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate tokio1_crate as tokio; use auto_enums::enum_derive; #[enum_derive(tokio1::AsyncRead)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/external/tokio/async_seek.expanded.rs000064400000000000000000000037701046102023000236770ustar 00000000000000extern crate tokio1_crate as tokio; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::tokio::io::AsyncSeek for Enum where A: ::tokio::io::AsyncSeek, B: ::tokio::io::AsyncSeek, { fn start_seek( self: ::core::pin::Pin<&mut Self>, pos: ::std::io::SeekFrom, ) -> ::std::io::Result<()> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::start_seek( ::core::pin::Pin::new_unchecked(x), pos, ) } Enum::B(x) => { ::start_seek( ::core::pin::Pin::new_unchecked(x), pos, ) } } } } fn poll_complete( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_complete( ::core::pin::Pin::new_unchecked(x), cx, ) } Enum::B(x) => { ::poll_complete( ::core::pin::Pin::new_unchecked(x), cx, ) } } } } } #[automatically_derived] impl ::core::marker::Unpin for Enum where A: ::core::marker::Unpin, B: ::core::marker::Unpin, {} const _: () = { trait MustNotImplDrop {} #[allow(clippy::drop_bounds, drop_bounds)] #[automatically_derived] impl MustNotImplDrop for T {} #[automatically_derived] impl MustNotImplDrop for Enum {} }; fn main() {} auto_enums-0.8.7/tests/expand/external/tokio/async_seek.rs000064400000000000000000000003121046102023000220750ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate tokio1_crate as tokio; use auto_enums::enum_derive; #[enum_derive(tokio1::AsyncSeek)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/external/tokio/async_write.expanded.rs000064400000000000000000000075231046102023000241020ustar 00000000000000extern crate tokio1_crate as tokio; use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::tokio::io::AsyncWrite for Enum where A: ::tokio::io::AsyncWrite, B: ::tokio::io::AsyncWrite, { fn is_write_vectored(&self) -> bool { match self { Enum::A(x) => ::is_write_vectored(x), Enum::B(x) => ::is_write_vectored(x), } } fn poll_write( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, buf: &[u8], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_write( ::core::pin::Pin::new_unchecked(x), cx, buf, ) } Enum::B(x) => { ::poll_write( ::core::pin::Pin::new_unchecked(x), cx, buf, ) } } } } fn poll_flush( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_flush( ::core::pin::Pin::new_unchecked(x), cx, ) } Enum::B(x) => { ::poll_flush( ::core::pin::Pin::new_unchecked(x), cx, ) } } } } fn poll_shutdown( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll<::std::io::Result<()>> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_shutdown( ::core::pin::Pin::new_unchecked(x), cx, ) } Enum::B(x) => { ::poll_shutdown( ::core::pin::Pin::new_unchecked(x), cx, ) } } } } fn poll_write_vectored( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, bufs: &[::std::io::IoSlice<'_>], ) -> ::core::task::Poll<::std::io::Result> { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll_write_vectored( ::core::pin::Pin::new_unchecked(x), cx, bufs, ) } Enum::B(x) => { ::poll_write_vectored( ::core::pin::Pin::new_unchecked(x), cx, bufs, ) } } } } } #[automatically_derived] impl ::core::marker::Unpin for Enum where A: ::core::marker::Unpin, B: ::core::marker::Unpin, {} const _: () = { trait MustNotImplDrop {} #[allow(clippy::drop_bounds, drop_bounds)] #[automatically_derived] impl MustNotImplDrop for T {} #[automatically_derived] impl MustNotImplDrop for Enum {} }; fn main() {} auto_enums-0.8.7/tests/expand/external/tokio/async_write.rs000064400000000000000000000003131046102023000223010ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate tokio1_crate as tokio; use auto_enums::enum_derive; #[enum_derive(tokio1::AsyncWrite)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/std/debug.expanded.rs000064400000000000000000000007321046102023000204570ustar 00000000000000use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::core::fmt::Debug for Enum where A: ::core::fmt::Debug, B: ::core::fmt::Debug, { #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { match self { Enum::A(x) => ::fmt(x, f), Enum::B(x) => ::fmt(x, f), } } } fn main() {} auto_enums-0.8.7/tests/expand/std/debug.rs000064400000000000000000000002311046102023000166620ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; #[enum_derive(Debug)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/std/error.expanded.rs000064400000000000000000000027621046102023000205270ustar 00000000000000use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::core::fmt::Display for Enum where A: ::core::fmt::Display, B: ::core::fmt::Display, { #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { match self { Enum::A(x) => ::fmt(x, f), Enum::B(x) => ::fmt(x, f), } } } #[automatically_derived] impl ::core::fmt::Debug for Enum where A: ::core::fmt::Debug, B: ::core::fmt::Debug, { #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { match self { Enum::A(x) => ::fmt(x, f), Enum::B(x) => ::fmt(x, f), } } } #[automatically_derived] impl ::std::error::Error for Enum where A: ::std::error::Error, B: ::std::error::Error, A: 'static, B: 'static, { #[allow(deprecated)] fn description(&self) -> &str { match self { Enum::A(x) => ::description(x), Enum::B(x) => ::description(x), } } fn source(&self) -> ::std::option::Option<&(dyn ::std::error::Error + 'static)> { match self { Enum::A(x) => ::std::option::Option::Some(x), Enum::B(x) => ::std::option::Option::Some(x), } } } fn main() {} auto_enums-0.8.7/tests/expand/std/error.rs000064400000000000000000000002311046102023000167250ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; #[enum_derive(Error)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/std/future.expanded.rs000064400000000000000000000026111046102023000207010ustar 00000000000000use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::core::future::Future for Enum where A: ::core::future::Future, B: ::core::future::Future::Output>, { type Output = ::Output; #[inline] fn poll( self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>, ) -> ::core::task::Poll { unsafe { match self.get_unchecked_mut() { Enum::A(x) => { ::poll( ::core::pin::Pin::new_unchecked(x), cx, ) } Enum::B(x) => { ::poll( ::core::pin::Pin::new_unchecked(x), cx, ) } } } } } #[automatically_derived] impl ::core::marker::Unpin for Enum where A: ::core::marker::Unpin, B: ::core::marker::Unpin, {} const _: () = { trait MustNotImplDrop {} #[allow(clippy::drop_bounds, drop_bounds)] #[automatically_derived] impl MustNotImplDrop for T {} #[automatically_derived] impl MustNotImplDrop for Enum {} }; fn main() {} auto_enums-0.8.7/tests/expand/std/future.rs000064400000000000000000000002321046102023000171070ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; #[enum_derive(Future)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/std/io/buf_read.expanded.rs000064400000000000000000000055511046102023000215530ustar 00000000000000use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::std::io::Read for Enum where A: ::std::io::Read, B: ::std::io::Read, { #[inline] fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result { match self { Enum::A(x) => ::read(x, buf), Enum::B(x) => ::read(x, buf), } } #[inline] fn read_vectored( &mut self, bufs: &mut [::std::io::IoSliceMut<'_>], ) -> ::std::io::Result { match self { Enum::A(x) => ::read_vectored(x, bufs), Enum::B(x) => ::read_vectored(x, bufs), } } #[inline] fn read_to_end( &mut self, buf: &mut ::std::vec::Vec, ) -> ::std::io::Result { match self { Enum::A(x) => ::read_to_end(x, buf), Enum::B(x) => ::read_to_end(x, buf), } } #[inline] fn read_to_string( &mut self, buf: &mut ::std::string::String, ) -> ::std::io::Result { match self { Enum::A(x) => ::read_to_string(x, buf), Enum::B(x) => ::read_to_string(x, buf), } } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> ::std::io::Result<()> { match self { Enum::A(x) => ::read_exact(x, buf), Enum::B(x) => ::read_exact(x, buf), } } } #[automatically_derived] impl ::std::io::BufRead for Enum where A: ::std::io::BufRead, B: ::std::io::BufRead, { #[inline] fn fill_buf(&mut self) -> ::std::io::Result<&[u8]> { match self { Enum::A(x) => ::fill_buf(x), Enum::B(x) => ::fill_buf(x), } } #[inline] fn consume(&mut self, amt: usize) { match self { Enum::A(x) => ::consume(x, amt), Enum::B(x) => ::consume(x, amt), } } #[inline] fn read_until( &mut self, byte: u8, buf: &mut ::std::vec::Vec, ) -> ::std::io::Result { match self { Enum::A(x) => ::read_until(x, byte, buf), Enum::B(x) => ::read_until(x, byte, buf), } } #[inline] fn read_line( &mut self, buf: &mut ::std::string::String, ) -> ::std::io::Result { match self { Enum::A(x) => ::read_line(x, buf), Enum::B(x) => ::read_line(x, buf), } } } fn main() {} auto_enums-0.8.7/tests/expand/std/io/buf_read.rs000064400000000000000000000002331046102023000177540ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; #[enum_derive(BufRead)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/std/io/read.expanded.rs000064400000000000000000000032031046102023000207070ustar 00000000000000use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::std::io::Read for Enum where A: ::std::io::Read, B: ::std::io::Read, { #[inline] fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result { match self { Enum::A(x) => ::read(x, buf), Enum::B(x) => ::read(x, buf), } } #[inline] fn read_vectored( &mut self, bufs: &mut [::std::io::IoSliceMut<'_>], ) -> ::std::io::Result { match self { Enum::A(x) => ::read_vectored(x, bufs), Enum::B(x) => ::read_vectored(x, bufs), } } #[inline] fn read_to_end( &mut self, buf: &mut ::std::vec::Vec, ) -> ::std::io::Result { match self { Enum::A(x) => ::read_to_end(x, buf), Enum::B(x) => ::read_to_end(x, buf), } } #[inline] fn read_to_string( &mut self, buf: &mut ::std::string::String, ) -> ::std::io::Result { match self { Enum::A(x) => ::read_to_string(x, buf), Enum::B(x) => ::read_to_string(x, buf), } } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> ::std::io::Result<()> { match self { Enum::A(x) => ::read_exact(x, buf), Enum::B(x) => ::read_exact(x, buf), } } } fn main() {} auto_enums-0.8.7/tests/expand/std/io/read.rs000064400000000000000000000002301046102023000171150ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; #[enum_derive(Read)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/std/io/seek.expanded.rs000064400000000000000000000007171046102023000207320ustar 00000000000000use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::std::io::Seek for Enum where A: ::std::io::Seek, B: ::std::io::Seek, { #[inline] fn seek(&mut self, pos: ::std::io::SeekFrom) -> ::std::io::Result { match self { Enum::A(x) => ::seek(x, pos), Enum::B(x) => ::seek(x, pos), } } } fn main() {} auto_enums-0.8.7/tests/expand/std/io/seek.rs000064400000000000000000000002301046102023000171310ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; #[enum_derive(Seek)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/std/io/write.expanded.rs000064400000000000000000000030051046102023000211260ustar 00000000000000use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::std::io::Write for Enum where A: ::std::io::Write, B: ::std::io::Write, { #[inline] fn write(&mut self, buf: &[u8]) -> ::std::io::Result { match self { Enum::A(x) => ::write(x, buf), Enum::B(x) => ::write(x, buf), } } #[inline] fn write_vectored( &mut self, bufs: &[::std::io::IoSlice<'_>], ) -> ::std::io::Result { match self { Enum::A(x) => ::write_vectored(x, bufs), Enum::B(x) => ::write_vectored(x, bufs), } } #[inline] fn flush(&mut self) -> ::std::io::Result<()> { match self { Enum::A(x) => ::flush(x), Enum::B(x) => ::flush(x), } } #[inline] fn write_all(&mut self, buf: &[u8]) -> ::std::io::Result<()> { match self { Enum::A(x) => ::write_all(x, buf), Enum::B(x) => ::write_all(x, buf), } } #[inline] fn write_fmt(&mut self, fmt: ::std::fmt::Arguments<'_>) -> ::std::io::Result<()> { match self { Enum::A(x) => ::write_fmt(x, fmt), Enum::B(x) => ::write_fmt(x, fmt), } } } fn main() {} auto_enums-0.8.7/tests/expand/std/io/write.rs000064400000000000000000000002311046102023000173350ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; #[enum_derive(Write)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/std/iter/double_ended_iterator.expanded.rs000064400000000000000000000133401046102023000246550ustar 00000000000000use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::core::iter::Iterator for Enum where A: ::core::iter::Iterator, B: ::core::iter::Iterator::Item>, { type Item = ::Item; #[inline] fn next(&mut self) -> ::core::option::Option { match self { Enum::A(x) => ::next(x), Enum::B(x) => ::next(x), } } #[inline] fn size_hint(&self) -> (usize, ::core::option::Option) { match self { Enum::A(x) => ::size_hint(x), Enum::B(x) => ::size_hint(x), } } #[inline] fn count(self) -> usize { match self { Enum::A(x) => ::count(x), Enum::B(x) => ::count(x), } } #[inline] fn last(self) -> ::core::option::Option { match self { Enum::A(x) => ::last(x), Enum::B(x) => ::last(x), } } #[inline] fn nth(&mut self, n: usize) -> ::core::option::Option { match self { Enum::A(x) => ::nth(x, n), Enum::B(x) => ::nth(x, n), } } #[inline] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] fn collect<__U: ::core::iter::FromIterator>(self) -> __U { match self { Enum::A(x) => ::collect(x), Enum::B(x) => ::collect(x), } } #[inline] fn partition<__U, __F>(self, f: __F) -> (__U, __U) where __U: ::core::default::Default + ::core::iter::Extend, __F: ::core::ops::FnMut(&Self::Item) -> bool, { match self { Enum::A(x) => ::partition(x, f), Enum::B(x) => ::partition(x, f), } } #[inline] fn fold<__U, __F>(self, init: __U, f: __F) -> __U where __F: ::core::ops::FnMut(__U, Self::Item) -> __U, { match self { Enum::A(x) => ::fold(x, init, f), Enum::B(x) => ::fold(x, init, f), } } #[inline] fn all<__F>(&mut self, f: __F) -> bool where __F: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::all(x, f), Enum::B(x) => ::all(x, f), } } #[inline] fn any<__F>(&mut self, f: __F) -> bool where __F: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::any(x, f), Enum::B(x) => ::any(x, f), } } #[inline] fn find<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(&Self::Item) -> bool, { match self { Enum::A(x) => ::find(x, predicate), Enum::B(x) => ::find(x, predicate), } } #[inline] fn find_map<__U, __F>(&mut self, f: __F) -> ::core::option::Option<__U> where __F: ::core::ops::FnMut(Self::Item) -> ::core::option::Option<__U>, { match self { Enum::A(x) => ::find_map(x, f), Enum::B(x) => ::find_map(x, f), } } #[inline] fn position<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::position(x, predicate), Enum::B(x) => ::position(x, predicate), } } } #[automatically_derived] impl ::core::iter::DoubleEndedIterator for Enum where A: ::core::iter::DoubleEndedIterator, B: ::core::iter::DoubleEndedIterator::Item>, { #[inline] fn next_back(&mut self) -> ::core::option::Option { match self { Enum::A(x) => ::next_back(x), Enum::B(x) => ::next_back(x), } } #[inline] fn nth_back(&mut self, n: usize) -> ::core::option::Option { match self { Enum::A(x) => ::nth_back(x, n), Enum::B(x) => ::nth_back(x, n), } } #[inline] fn rfold<__U, __F>(self, init: __U, f: __F) -> __U where __F: ::core::ops::FnMut(__U, Self::Item) -> __U, { match self { Enum::A(x) => ::rfold(x, init, f), Enum::B(x) => ::rfold(x, init, f), } } #[inline] fn rfind<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(&Self::Item) -> bool, { match self { Enum::A(x) => ::rfind(x, predicate), Enum::B(x) => ::rfind(x, predicate), } } } fn main() {} auto_enums-0.8.7/tests/expand/std/iter/double_ended_iterator.rs000064400000000000000000000002471046102023000230700ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; #[enum_derive(DoubleEndedIterator)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/std/iter/exact_size_iterator.expanded.rs000064400000000000000000000112341046102023000244020ustar 00000000000000use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::core::iter::Iterator for Enum where A: ::core::iter::Iterator, B: ::core::iter::Iterator::Item>, { type Item = ::Item; #[inline] fn next(&mut self) -> ::core::option::Option { match self { Enum::A(x) => ::next(x), Enum::B(x) => ::next(x), } } #[inline] fn size_hint(&self) -> (usize, ::core::option::Option) { match self { Enum::A(x) => ::size_hint(x), Enum::B(x) => ::size_hint(x), } } #[inline] fn count(self) -> usize { match self { Enum::A(x) => ::count(x), Enum::B(x) => ::count(x), } } #[inline] fn last(self) -> ::core::option::Option { match self { Enum::A(x) => ::last(x), Enum::B(x) => ::last(x), } } #[inline] fn nth(&mut self, n: usize) -> ::core::option::Option { match self { Enum::A(x) => ::nth(x, n), Enum::B(x) => ::nth(x, n), } } #[inline] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] fn collect<__U: ::core::iter::FromIterator>(self) -> __U { match self { Enum::A(x) => ::collect(x), Enum::B(x) => ::collect(x), } } #[inline] fn partition<__U, __F>(self, f: __F) -> (__U, __U) where __U: ::core::default::Default + ::core::iter::Extend, __F: ::core::ops::FnMut(&Self::Item) -> bool, { match self { Enum::A(x) => ::partition(x, f), Enum::B(x) => ::partition(x, f), } } #[inline] fn fold<__U, __F>(self, init: __U, f: __F) -> __U where __F: ::core::ops::FnMut(__U, Self::Item) -> __U, { match self { Enum::A(x) => ::fold(x, init, f), Enum::B(x) => ::fold(x, init, f), } } #[inline] fn all<__F>(&mut self, f: __F) -> bool where __F: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::all(x, f), Enum::B(x) => ::all(x, f), } } #[inline] fn any<__F>(&mut self, f: __F) -> bool where __F: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::any(x, f), Enum::B(x) => ::any(x, f), } } #[inline] fn find<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(&Self::Item) -> bool, { match self { Enum::A(x) => ::find(x, predicate), Enum::B(x) => ::find(x, predicate), } } #[inline] fn find_map<__U, __F>(&mut self, f: __F) -> ::core::option::Option<__U> where __F: ::core::ops::FnMut(Self::Item) -> ::core::option::Option<__U>, { match self { Enum::A(x) => ::find_map(x, f), Enum::B(x) => ::find_map(x, f), } } #[inline] fn position<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::position(x, predicate), Enum::B(x) => ::position(x, predicate), } } } #[automatically_derived] impl ::core::iter::ExactSizeIterator for Enum where A: ::core::iter::ExactSizeIterator, B: ::core::iter::ExactSizeIterator::Item>, { #[inline] fn len(&self) -> usize { match self { Enum::A(x) => ::len(x), Enum::B(x) => ::len(x), } } } fn main() {} auto_enums-0.8.7/tests/expand/std/iter/exact_size_iterator.rs000064400000000000000000000002451046102023000226130ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; #[enum_derive(ExactSizeIterator)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/std/iter/extend.expanded.rs000064400000000000000000000010221046102023000216140ustar 00000000000000use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::core::iter::Extend<__A> for Enum where A: ::core::iter::Extend<__A>, B: ::core::iter::Extend<__A>, { #[inline] fn extend<__T: ::core::iter::IntoIterator>(&mut self, iter: __T) { match self { Enum::A(x) => >::extend(x, iter), Enum::B(x) => >::extend(x, iter), } } } fn main() {} auto_enums-0.8.7/tests/expand/std/iter/extend.rs000064400000000000000000000002321046102023000200270ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; #[enum_derive(Extend)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/std/iter/fused_iterator.expanded.rs000064400000000000000000000106531046102023000233560ustar 00000000000000use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::core::iter::Iterator for Enum where A: ::core::iter::Iterator, B: ::core::iter::Iterator::Item>, { type Item = ::Item; #[inline] fn next(&mut self) -> ::core::option::Option { match self { Enum::A(x) => ::next(x), Enum::B(x) => ::next(x), } } #[inline] fn size_hint(&self) -> (usize, ::core::option::Option) { match self { Enum::A(x) => ::size_hint(x), Enum::B(x) => ::size_hint(x), } } #[inline] fn count(self) -> usize { match self { Enum::A(x) => ::count(x), Enum::B(x) => ::count(x), } } #[inline] fn last(self) -> ::core::option::Option { match self { Enum::A(x) => ::last(x), Enum::B(x) => ::last(x), } } #[inline] fn nth(&mut self, n: usize) -> ::core::option::Option { match self { Enum::A(x) => ::nth(x, n), Enum::B(x) => ::nth(x, n), } } #[inline] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] fn collect<__U: ::core::iter::FromIterator>(self) -> __U { match self { Enum::A(x) => ::collect(x), Enum::B(x) => ::collect(x), } } #[inline] fn partition<__U, __F>(self, f: __F) -> (__U, __U) where __U: ::core::default::Default + ::core::iter::Extend, __F: ::core::ops::FnMut(&Self::Item) -> bool, { match self { Enum::A(x) => ::partition(x, f), Enum::B(x) => ::partition(x, f), } } #[inline] fn fold<__U, __F>(self, init: __U, f: __F) -> __U where __F: ::core::ops::FnMut(__U, Self::Item) -> __U, { match self { Enum::A(x) => ::fold(x, init, f), Enum::B(x) => ::fold(x, init, f), } } #[inline] fn all<__F>(&mut self, f: __F) -> bool where __F: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::all(x, f), Enum::B(x) => ::all(x, f), } } #[inline] fn any<__F>(&mut self, f: __F) -> bool where __F: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::any(x, f), Enum::B(x) => ::any(x, f), } } #[inline] fn find<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(&Self::Item) -> bool, { match self { Enum::A(x) => ::find(x, predicate), Enum::B(x) => ::find(x, predicate), } } #[inline] fn find_map<__U, __F>(&mut self, f: __F) -> ::core::option::Option<__U> where __F: ::core::ops::FnMut(Self::Item) -> ::core::option::Option<__U>, { match self { Enum::A(x) => ::find_map(x, f), Enum::B(x) => ::find_map(x, f), } } #[inline] fn position<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::position(x, predicate), Enum::B(x) => ::position(x, predicate), } } } #[automatically_derived] impl ::core::iter::FusedIterator for Enum where A: ::core::iter::FusedIterator, B: ::core::iter::FusedIterator::Item>, {} fn main() {} auto_enums-0.8.7/tests/expand/std/iter/fused_iterator.rs000064400000000000000000000002411046102023000215570ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; #[enum_derive(FusedIterator)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/std/iter/iterator.expanded.rs000064400000000000000000000103371046102023000221670ustar 00000000000000use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::core::iter::Iterator for Enum where A: ::core::iter::Iterator, B: ::core::iter::Iterator::Item>, { type Item = ::Item; #[inline] fn next(&mut self) -> ::core::option::Option { match self { Enum::A(x) => ::next(x), Enum::B(x) => ::next(x), } } #[inline] fn size_hint(&self) -> (usize, ::core::option::Option) { match self { Enum::A(x) => ::size_hint(x), Enum::B(x) => ::size_hint(x), } } #[inline] fn count(self) -> usize { match self { Enum::A(x) => ::count(x), Enum::B(x) => ::count(x), } } #[inline] fn last(self) -> ::core::option::Option { match self { Enum::A(x) => ::last(x), Enum::B(x) => ::last(x), } } #[inline] fn nth(&mut self, n: usize) -> ::core::option::Option { match self { Enum::A(x) => ::nth(x, n), Enum::B(x) => ::nth(x, n), } } #[inline] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] fn collect<__U: ::core::iter::FromIterator>(self) -> __U { match self { Enum::A(x) => ::collect(x), Enum::B(x) => ::collect(x), } } #[inline] fn partition<__U, __F>(self, f: __F) -> (__U, __U) where __U: ::core::default::Default + ::core::iter::Extend, __F: ::core::ops::FnMut(&Self::Item) -> bool, { match self { Enum::A(x) => ::partition(x, f), Enum::B(x) => ::partition(x, f), } } #[inline] fn fold<__U, __F>(self, init: __U, f: __F) -> __U where __F: ::core::ops::FnMut(__U, Self::Item) -> __U, { match self { Enum::A(x) => ::fold(x, init, f), Enum::B(x) => ::fold(x, init, f), } } #[inline] fn all<__F>(&mut self, f: __F) -> bool where __F: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::all(x, f), Enum::B(x) => ::all(x, f), } } #[inline] fn any<__F>(&mut self, f: __F) -> bool where __F: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::any(x, f), Enum::B(x) => ::any(x, f), } } #[inline] fn find<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(&Self::Item) -> bool, { match self { Enum::A(x) => ::find(x, predicate), Enum::B(x) => ::find(x, predicate), } } #[inline] fn find_map<__U, __F>(&mut self, f: __F) -> ::core::option::Option<__U> where __F: ::core::ops::FnMut(Self::Item) -> ::core::option::Option<__U>, { match self { Enum::A(x) => ::find_map(x, f), Enum::B(x) => ::find_map(x, f), } } #[inline] fn position<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::position(x, predicate), Enum::B(x) => ::position(x, predicate), } } } fn main() {} auto_enums-0.8.7/tests/expand/std/iter/iterator.rs000064400000000000000000000002341046102023000203730ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; #[enum_derive(Iterator)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expand/std/iter/trusted_len.expanded.rs000064400000000000000000000106511046102023000226650ustar 00000000000000use auto_enums::enum_derive; enum Enum { A(A), B(B), } #[automatically_derived] impl ::core::iter::Iterator for Enum where A: ::core::iter::Iterator, B: ::core::iter::Iterator::Item>, { type Item = ::Item; #[inline] fn next(&mut self) -> ::core::option::Option { match self { Enum::A(x) => ::next(x), Enum::B(x) => ::next(x), } } #[inline] fn size_hint(&self) -> (usize, ::core::option::Option) { match self { Enum::A(x) => ::size_hint(x), Enum::B(x) => ::size_hint(x), } } #[inline] fn count(self) -> usize { match self { Enum::A(x) => ::count(x), Enum::B(x) => ::count(x), } } #[inline] fn last(self) -> ::core::option::Option { match self { Enum::A(x) => ::last(x), Enum::B(x) => ::last(x), } } #[inline] fn nth(&mut self, n: usize) -> ::core::option::Option { match self { Enum::A(x) => ::nth(x, n), Enum::B(x) => ::nth(x, n), } } #[inline] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] fn collect<__U: ::core::iter::FromIterator>(self) -> __U { match self { Enum::A(x) => ::collect(x), Enum::B(x) => ::collect(x), } } #[inline] fn partition<__U, __F>(self, f: __F) -> (__U, __U) where __U: ::core::default::Default + ::core::iter::Extend, __F: ::core::ops::FnMut(&Self::Item) -> bool, { match self { Enum::A(x) => ::partition(x, f), Enum::B(x) => ::partition(x, f), } } #[inline] fn fold<__U, __F>(self, init: __U, f: __F) -> __U where __F: ::core::ops::FnMut(__U, Self::Item) -> __U, { match self { Enum::A(x) => ::fold(x, init, f), Enum::B(x) => ::fold(x, init, f), } } #[inline] fn all<__F>(&mut self, f: __F) -> bool where __F: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::all(x, f), Enum::B(x) => ::all(x, f), } } #[inline] fn any<__F>(&mut self, f: __F) -> bool where __F: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::any(x, f), Enum::B(x) => ::any(x, f), } } #[inline] fn find<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(&Self::Item) -> bool, { match self { Enum::A(x) => ::find(x, predicate), Enum::B(x) => ::find(x, predicate), } } #[inline] fn find_map<__U, __F>(&mut self, f: __F) -> ::core::option::Option<__U> where __F: ::core::ops::FnMut(Self::Item) -> ::core::option::Option<__U>, { match self { Enum::A(x) => ::find_map(x, f), Enum::B(x) => ::find_map(x, f), } } #[inline] fn position<__P>(&mut self, predicate: __P) -> ::core::option::Option where __P: ::core::ops::FnMut(Self::Item) -> bool, { match self { Enum::A(x) => ::position(x, predicate), Enum::B(x) => ::position(x, predicate), } } } #[automatically_derived] unsafe impl ::core::iter::TrustedLen for Enum where A: ::core::iter::TrustedLen, B: ::core::iter::TrustedLen::Item>, {} fn main() {} auto_enums-0.8.7/tests/expand/std/iter/trusted_len.rs000064400000000000000000000002361046102023000210740ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; #[enum_derive(TrustedLen)] enum Enum { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/expandtest.rs000064400000000000000000000003501046102023000157040ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT #![cfg(not(miri))] #[rustversion::attr(not(nightly), ignore)] #[test] fn expandtest() { let args = &["--all-features"]; macrotest::expand_args("tests/expand/**/*.rs", args); } auto_enums-0.8.7/tests/run-pass/futures01.rs000064400000000000000000000003701046102023000171350ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate futures01_crate as futures; use auto_enums::enum_derive; #[enum_derive(futures01::Future, futures01::Sink, futures01::Stream)] enum Futures01 { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/run-pass/futures03.rs000064400000000000000000000005331046102023000171400ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate futures03_crate as futures; use auto_enums::enum_derive; #[enum_derive( futures03::Stream, futures03::Sink, futures03::AsyncRead, futures03::AsyncWrite, futures03::AsyncSeek, futures03::AsyncBufRead )] enum Futures03 { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/run-pass/http_body1.rs000064400000000000000000000003261046102023000173550ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate http_body1_crate as http_body; use auto_enums::enum_derive; #[enum_derive(http_body1::Body)] enum HttpBody1 { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/run-pass/rayon.rs000064400000000000000000000004071046102023000164300ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate rayon_crate as rayon; use auto_enums::enum_derive; #[enum_derive(rayon::ParallelIterator, rayon::IndexedParallelIterator, rayon::ParallelExtend)] enum Rayon { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/run-pass/serde.rs000064400000000000000000000003111046102023000163740ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate serde_crate as serde; use auto_enums::enum_derive; #[enum_derive(serde::Serialize)] enum Serde { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/run-pass/tokio01.rs000064400000000000000000000003611046102023000165650ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate tokio01_crate as tokio; use auto_enums::enum_derive; #[enum_derive(tokio01::AsyncRead, tokio01::AsyncWrite, Read, Write)] enum Tokio01 { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/run-pass/tokio02.rs000064400000000000000000000004171046102023000165700ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate tokio02_crate as tokio; use auto_enums::enum_derive; #[enum_derive(tokio02::AsyncRead, tokio02::AsyncWrite, tokio02::AsyncSeek, tokio02::AsyncBufRead)] enum Tokio02 { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/run-pass/tokio03.rs000064400000000000000000000004171046102023000165710ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate tokio03_crate as tokio; use auto_enums::enum_derive; #[enum_derive(tokio03::AsyncRead, tokio03::AsyncWrite, tokio03::AsyncSeek, tokio03::AsyncBufRead)] enum Tokio03 { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/run-pass/tokio1.rs000064400000000000000000000004111046102023000165010ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT extern crate tokio1_crate as tokio; use auto_enums::enum_derive; #[enum_derive(tokio1::AsyncRead, tokio1::AsyncWrite, tokio1::AsyncSeek, tokio1::AsyncBufRead)] enum Tokio1 { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/type_analysis.rs000064400000000000000000000042341046102023000164160ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT #![cfg(feature = "type_analysis")] #![allow(dead_code)] use std::fmt; use auto_enums::auto_enum; #[test] fn func() { #[auto_enum] // there is no need to specify std library's traits fn test1(x: i32) -> impl Iterator { match x { 0 => 1..10, _ => vec![5, 10].into_iter(), } } #[auto_enum] // this is handled as a dummy attribute. fn test2(x: i32) -> impl Iterator { #[auto_enum(Iterator)] match x { 0 => 1..10, _ => vec![5, 10].into_iter(), } } #[auto_enum] // there is no need to specify std library's traits fn test3(x: i32) -> impl Iterator { match x { 0 => return 1..10, _ => vec![5, 10].into_iter(), } } #[auto_enum] // this is handled as a dummy attribute. fn test4(x: i32) -> impl Iterator { #[auto_enum(Iterator)] let iter = match x { 0 => 1..10, 1 => 11..=20, _ => return vec![5, 10].into_iter(), }; iter.collect::>().into_iter() } #[auto_enum] fn break_in_loop(mut x: i32) -> impl Iterator { loop { if x < 0 { break x..0; } else if x % 5 == 0 { break 0..=x; } x -= 1; } } #[auto_enum] fn return_in_loop(mut x: i32) -> impl Iterator { loop { if x < 0 { return x..0; } else if x % 5 == 0 { return 0..=x; } x -= 1; } } } #[test] fn local() { #[auto_enum] fn test1(x: i32) { #[auto_enum] let _y: impl Iterator = match x { 0 => 1..10, _ => vec![5, 10].into_iter(), }; } #[auto_enum] fn test2(x: i32) -> impl Iterator + fmt::Debug { #[auto_enum(fmt::Debug)] let y: impl Iterator = match x { 0 => 1..10, _ => vec![5, 10].into_iter(), }; y } } auto_enums-0.8.7/tests/ui/auto_enum/args.rs000064400000000000000000000034101046102023000170720ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::auto_enum; #[auto_enum(Iterator;)] //~ ERROR expected `,` fn unexpected_token_1(x: usize) -> impl Iterator { match x { 0 => 1..=8, _ => 0..2, } } #[auto_enum(Iterator,;)] //~ ERROR expected identifier fn unexpected_token_2(x: usize) -> impl Iterator { match x { 0 => 1..=8, _ => 0..2, } } mod marker { use auto_enums::auto_enum; #[auto_enum(marker{f}, Iterator)] //~ ERROR expected `,` fn marker_invalid_delimiter_1(x: usize) -> impl Iterator { match x { 0 => 1..=8, _ => 0..2, } } #[auto_enum(marker[f], Iterator)] //~ ERROR expected `,` fn marker_invalid_delimiter_2(x: usize) -> impl Iterator { match x { 0 => 1..=8, _ => 0..2, } } #[auto_enum(marker(f), Iterator)] //~ ERROR expected `,` fn marker_removed_delimiter(x: usize) -> impl Iterator { match x { 0 => 1..=8, _ => 0..2, } } #[auto_enum(marker = f, marker = g, Iterator)] //~ ERROR duplicate `marker` argument fn multiple_marker(x: usize) -> impl Iterator { match x { 0 => 1..=8, _ => 0..2, } } #[auto_enum(marker =, Iterator)] //~ ERROR expected identifier fn empty_marker(x: usize) -> impl Iterator { match x { 0 => 1..=8, _ => 0..2, } } #[auto_enum(marker = f t, Iterator)] //~ ERROR expected `,` fn marker_multiple_ident(x: usize) -> impl Iterator { match x { 0 => 1..=8, _ => 0..2, } } } fn main() {} auto_enums-0.8.7/tests/ui/auto_enum/args.stderr000064400000000000000000000024671046102023000177640ustar 00000000000000error: expected `,` --> tests/ui/auto_enum/args.rs:5:21 | 5 | #[auto_enum(Iterator;)] //~ ERROR expected `,` | ^ error: expected identifier --> tests/ui/auto_enum/args.rs:13:22 | 13 | #[auto_enum(Iterator,;)] //~ ERROR expected identifier | ^ error: expected `,` --> tests/ui/auto_enum/args.rs:24:23 | 24 | #[auto_enum(marker{f}, Iterator)] //~ ERROR expected `,` | ^ error: expected `,` --> tests/ui/auto_enum/args.rs:32:23 | 32 | #[auto_enum(marker[f], Iterator)] //~ ERROR expected `,` | ^ error: expected `,` --> tests/ui/auto_enum/args.rs:40:23 | 40 | #[auto_enum(marker(f), Iterator)] //~ ERROR expected `,` | ^ error: duplicate `marker` argument --> tests/ui/auto_enum/args.rs:48:29 | 48 | #[auto_enum(marker = f, marker = g, Iterator)] //~ ERROR duplicate `marker` argument | ^^^^^^ error: expected identifier --> tests/ui/auto_enum/args.rs:56:25 | 56 | #[auto_enum(marker =, Iterator)] //~ ERROR expected identifier | ^ error: expected `,` --> tests/ui/auto_enum/args.rs:64:28 | 64 | #[auto_enum(marker = f t, Iterator)] //~ ERROR expected `,` | ^ auto_enums-0.8.7/tests/ui/auto_enum/attribute.rs000064400000000000000000000015011046102023000201400ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::auto_enum; #[auto_enum(Iterator)] fn unexpected_token_in_never(x: usize) -> impl Iterator { match x { 0 => 1..8, #[never(foo)] //~ ERROR unexpected token 1 => panic!(), _ => (0..2).map(|x| x + 1), } } #[auto_enum(Iterator)] fn unexpected_token_in_nested(x: usize) -> impl Iterator { match x { 0 => 1..8, #[nested(foo)] //~ ERROR unexpected token 1 => panic!(), _ => (0..2).map(|x| x + 1), } } #[auto_enum(Iterator)] fn removed_rec(x: usize) -> impl Iterator { match x { 0 => 1..8, #[rec] //~ ERROR #[rec] has been removed and replaced with #[nested] 1 => panic!(), _ => (0..2).map(|x| x + 1), } } fn main() {} auto_enums-0.8.7/tests/ui/auto_enum/attribute.stderr000064400000000000000000000010241046102023000210170ustar 00000000000000error: unexpected token in attribute --> tests/ui/auto_enum/attribute.rs:9:16 | 9 | #[never(foo)] //~ ERROR unexpected token | ^ error: unexpected token in attribute --> tests/ui/auto_enum/attribute.rs:19:17 | 19 | #[nested(foo)] //~ ERROR unexpected token | ^ error: #[rec] has been removed and replaced with #[nested] --> tests/ui/auto_enum/attribute.rs:29:9 | 29 | #[rec] //~ ERROR #[rec] has been removed and replaced with #[nested] | ^^^^^^ auto_enums-0.8.7/tests/ui/auto_enum/compile-fail.rs000064400000000000000000000037041046102023000205050ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::auto_enum; #[auto_enum(Iterator)] fn if_missing_else(x: usize) -> impl Iterator { if x == 0 { 1..8 } else if x > 3 { //~^ ERROR `if` expression missing an else clause 2..=10 } } #[auto_enum(Iterator)] fn return1(x: i32, y: i32) -> impl Iterator { #[auto_enum(Iterator)] let iter = match x { //~^ ERROR `#[auto_enum]` is required two or more branches or marker macros in total, there is only one branch or marker macro in this statement _ if y < 0 => return y..=0, _ => 2..=10, }; match y { 0 => iter.flat_map(|x| 0..x), _ => iter.map(|x| x + 1), } } #[auto_enum(Iterator)] fn return0(x: i32, y: i32) -> impl Iterator { #[auto_enum(Iterator)] let iter = match x { //~^ ERROR `#[auto_enum]` is required two or more branches or marker macros in total, there is no branch or marker macro in this statement _ if y < 0 => return y..=0, _ => return 2..=10, }; match y { 0 => iter.flat_map(|x| 0..x), _ => iter.map(|x| x + 1), } } #[auto_enum(Iterator)] fn multi_error(x: i32, y: i32) -> impl Iterator { #[auto_enum(Iterator)] let iter = match x { //~^ ERROR `#[auto_enum]` is required two or more branches or marker macros in total, there is only one branch or marker macro in this statement _ if y < 0 => return y..=0, _ => { #[auto_enum(Iterator)] let _iter = match x { //~^ ERROR `#[auto_enum]` is required two or more branches or marker macros in total, there is only one branch or marker macro in this statement _ if y < 0 => return y..=0, _ => 2..=10, }; 2..=10 } }; match y { 0 => iter.flat_map(|x| 0..x), _ => iter.map(|x| x + 1), } } fn main() {} auto_enums-0.8.7/tests/ui/auto_enum/compile-fail.stderr000064400000000000000000000037711046102023000213700ustar 00000000000000error: `if` expression missing an else clause --> tests/ui/auto_enum/compile-fail.rs:9:12 | 9 | } else if x > 3 { | ^^ error: `#[auto_enum]` is required two or more branches or marker macros in total, there is only one branch or marker macro in this statement --> tests/ui/auto_enum/compile-fail.rs:18:5 | 18 | / let iter = match x { 19 | | //~^ ERROR `#[auto_enum]` is required two or more branches or marker macros in total, there is only one branch or marker macro in... 20 | | _ if y < 0 => return y..=0, 21 | | _ => 2..=10, 22 | | }; | |______^ error: `#[auto_enum]` is required two or more branches or marker macros in total, there is no branch or marker macro in this statement --> tests/ui/auto_enum/compile-fail.rs:33:5 | 33 | / let iter = match x { 34 | | //~^ ERROR `#[auto_enum]` is required two or more branches or marker macros in total, there is no branch or marker macro in this ... 35 | | _ if y < 0 => return y..=0, 36 | | _ => return 2..=10, 37 | | }; | |______^ error: `#[auto_enum]` is required two or more branches or marker macros in total, there is only one branch or marker macro in this statement --> tests/ui/auto_enum/compile-fail.rs:53:13 | 53 | / ... let _iter = match x { 54 | | ... //~^ ERROR `#[auto_enum]` is required two or more branches or marker macros in total, there is only one branch or marker macro ... 55 | | ... _ if y < 0 => return y..=0, 56 | | ... _ => 2..=10, 57 | | ... }; | |________^ error: `#[auto_enum]` is required two or more branches or marker macros in total, there is only one branch or marker macro in this statement --> tests/ui/auto_enum/compile-fail.rs:48:5 | 48 | / let iter = match x { 49 | | //~^ ERROR `#[auto_enum]` is required two or more branches or marker macros in total, there is only one branch or marker macro in... 50 | | _ if y < 0 => return y..=0, 51 | | _ => { ... | 60 | | }; | |______^ auto_enums-0.8.7/tests/ui/auto_enum/invalid_break.rs000064400000000000000000000002731046102023000207340ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT fn closure() -> impl Fn() { || break } fn async_block() -> impl std::future::Future { async { break } } fn main() {} auto_enums-0.8.7/tests/ui/auto_enum/invalid_break.stderr000064400000000000000000000006361046102023000216160ustar 00000000000000error[E0267]: `break` inside of a closure --> tests/ui/auto_enum/invalid_break.rs:4:8 | 4 | || break | -- ^^^^^ cannot `break` inside of a closure | | | enclosing closure error[E0267]: `break` inside `async` block --> tests/ui/auto_enum/invalid_break.rs:8:13 | 8 | async { break } | ----- ^^^^^ cannot `break` inside `async` block | | | enclosing `async` block auto_enums-0.8.7/tests/ui/auto_enum/marker.rs000064400000000000000000000016501046102023000174230ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::auto_enum; #[auto_enum(Iterator, marker = foo)] fn a(x: usize) -> impl Iterator { #[auto_enum(Iterator, marker = foo)] //~ ERROR a custom marker name is specified that duplicated the name already used in the parent scope let _iter = match x { 0 => 1..8, 1 => return foo!(1..9), _ => (0..2).map(|x| x + 1), }; match x { 0 => 1..8, _ => (0..2).map(|x| x + 1), } } #[auto_enum(Iterator, marker = foo)] fn b(x: usize) -> impl Iterator { #[auto_enum(Iterator, marker = bar)] let _iter = match x { 0 => 1..8, 1 => return foo!(1..9), // OK 2 => return marker!(1..9), //~ ERROR cannot find macro `marker!` in this scope _ => (0..2).map(|x| x + 1), }; match x { 0 => 1..8, _ => (0..2).map(|x| x + 1), } } fn main() {} auto_enums-0.8.7/tests/ui/auto_enum/marker.stderr000064400000000000000000000010131046102023000202730ustar 00000000000000error: a custom marker name is specified that duplicated the name already used in the parent scope --> tests/ui/auto_enum/marker.rs:7:36 | 7 | #[auto_enum(Iterator, marker = foo)] | ^^^ error: cannot find macro `marker` in this scope --> tests/ui/auto_enum/marker.rs:27:21 | 27 | 2 => return marker!(1..9), //~ ERROR cannot find macro `marker!` in this scope | ^^^^^^ | = note: `marker` is in scope, but it is an attribute: `#[marker]` auto_enums-0.8.7/tests/ui/enum_derive/args.rs000064400000000000000000000007301046102023000174020ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; #[enum_derive(Clone, =>)] //~ ERROR expected identifier enum Enum1 { A(A), B(B), } #[enum_derive(foo::bar::!)] //~ ERROR expected identifier enum Enum2 { A(A), B(B), } #[enum_derive(Clone, Foo:)] //~ ERROR expected `,` enum Enum3 { A(A), B(B), } #[enum_derive(Clone Foo)] //~ ERROR expected `,` enum Enum4 { A(A), B(B), } fn main() {} auto_enums-0.8.7/tests/ui/enum_derive/args.stderr000064400000000000000000000011651046102023000202640ustar 00000000000000error: expected identifier --> tests/ui/enum_derive/args.rs:5:22 | 5 | #[enum_derive(Clone, =>)] //~ ERROR expected identifier | ^ error: expected identifier --> tests/ui/enum_derive/args.rs:11:25 | 11 | #[enum_derive(foo::bar::!)] //~ ERROR expected identifier | ^ error: expected `,` --> tests/ui/enum_derive/args.rs:17:25 | 17 | #[enum_derive(Clone, Foo:)] //~ ERROR expected `,` | ^ error: expected `,` --> tests/ui/enum_derive/args.rs:23:21 | 23 | #[enum_derive(Clone Foo)] //~ ERROR expected `,` | ^^^ auto_enums-0.8.7/tests/ui/enum_derive/ty_impls.rs000064400000000000000000000003751046102023000203130ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use auto_enums::enum_derive; struct Foo(A); #[enum_derive(Transpose)] enum Enum1 { //~^ ERROR `enum_derive(Transpose)` all fields need to be generics A(Foo), B(B), } fn main() {} auto_enums-0.8.7/tests/ui/enum_derive/ty_impls.stderr000064400000000000000000000004201046102023000211610ustar 00000000000000error: `enum_derive(Transpose)` all fields need to be generics --> tests/ui/enum_derive/ty_impls.rs:8:1 | 8 | / enum Enum1 { 9 | | //~^ ERROR `enum_derive(Transpose)` all fields need to be generics 10 | | A(Foo), 11 | | B(B), 12 | | } | |_^ auto_enums-0.8.7/tests/ui/enum_derive/unpin.rs000064400000000000000000000010341046102023000175750ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 OR MIT use core::{ future::Future, marker::PhantomPinned, pin::Pin, task::{Context, Poll}, }; use auto_enums::enum_derive; #[enum_derive(Future)] //~ ERROR cannot be unpinned enum Enum1 { A(PinnedFuture), } struct PinnedFuture(PhantomPinned); impl Future for PinnedFuture { type Output = (); fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { Poll::Pending } } fn main() { fn is_unpin() {} is_unpin::(); } auto_enums-0.8.7/tests/ui/enum_derive/unpin.stderr000064400000000000000000000037271046102023000204670ustar 00000000000000error[E0277]: `PhantomPinned` cannot be unpinned --> tests/ui/enum_derive/unpin.rs:12:1 | 12 | #[enum_derive(Future)] //~ ERROR cannot be unpinned | ^^^^^^^^^^^^^^^^^^^^^^ within `PinnedFuture`, the trait `Unpin` is not implemented for `PhantomPinned` | = note: consider using the `pin!` macro consider using `Box::pin` if you need to access the pinned value outside of the current scope note: required because it appears within the type `PinnedFuture` --> tests/ui/enum_derive/unpin.rs:17:8 | 17 | struct PinnedFuture(PhantomPinned); | ^^^^^^^^^^^^ = help: see issue #48214 = note: this error originates in the attribute macro `enum_derive` (in Nightly builds, run with -Z macro-backtrace for more info) help: add `#![feature(trivial_bounds)]` to the crate attributes to enable | 3 + #![feature(trivial_bounds)] | error[E0277]: `PhantomPinned` cannot be unpinned --> tests/ui/enum_derive/unpin.rs:28:16 | 28 | is_unpin::(); | ^^^^^ within `PinnedFuture`, the trait `Unpin` is not implemented for `PhantomPinned` | = note: consider using the `pin!` macro consider using `Box::pin` if you need to access the pinned value outside of the current scope note: required because it appears within the type `PinnedFuture` --> tests/ui/enum_derive/unpin.rs:17:8 | 17 | struct PinnedFuture(PhantomPinned); | ^^^^^^^^^^^^ note: required for `Enum1` to implement `Unpin` --> tests/ui/enum_derive/unpin.rs:12:1 | 12 | #[enum_derive(Future)] //~ ERROR cannot be unpinned | ^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here 13 | enum Enum1 { | ^^^^^ note: required by a bound in `is_unpin` --> tests/ui/enum_derive/unpin.rs:27:20 | 27 | fn is_unpin() {} | ^^^^^ required by this bound in `is_unpin` = note: this error originates in the attribute macro `enum_derive` (in Nightly builds, run with -Z macro-backtrace for more info)