derivative-2.2.0/.github/ISSUE_TEMPLATE/bug_report.md010064400362620024044000000014011400305350200203060ustar0000000000000000--- name: Bug report about: Create a report to help us improve title: Title (eg. attribute `X` does not work as expected on Mondays) labels: bug assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Include minimum complete example reproducing the problem. **Expected behavior** A clear and concise description of what you expected to happen. **Errors** Compiler error if relevant. **Version (please complete the following information):** Please include the output of the following commands, and any other version you think is relevant: ```sh rustup --version cargo --version rustc --version ``` - Version of `derivative`: [e.g. 1.0.3] **Additional context** Add any other context about the problem here. derivative-2.2.0/.github/workflows/doc.yml010064400362620024044000000017441400305350200167700ustar0000000000000000on: [push] name: Deploy documentation jobs: deploy: name: Deploy documentation runs-on: ubuntu-latest steps: - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true - run: cargo +stable install mdbook --no-default-features --features search --vers "^0.4.0" - uses: actions/checkout@v2 with: path: code - run: mdbook build working-directory: code - uses: actions/checkout@v2 with: path: doc ref: gh-pages - run: | mkdir -p doc/branches rm -fr doc/branches/${GITHUB_REF##*/} mv code/book doc/branches/${GITHUB_REF##*/} - working-directory: doc run: | git config user.name bot git config user.email bot@bot git add . git diff-index --quiet HEAD || git commit -m "Autogenerate documentation for branch ${GITHUB_REF##*/}" git pushderivative-2.2.0/.github/workflows/main.yml010064400362620024044000000053201400305350200171410ustar0000000000000000on: [push, pull_request] name: Continuous integration jobs: check: name: Check runs-on: ubuntu-latest strategy: matrix: rust: - 1.34.0 - stable - beta - nightly steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.rust }} override: true - uses: actions-rs/cargo@v1 with: command: check test: name: Test Suite runs-on: ${{ matrix.os }} strategy: matrix: os: - ubuntu-18.04 - macos-latest - windows-latest rust: - 1.34.0 - stable - beta - nightly features: - '' - 'use_core' extra_args: - '' include: # The compiler output isn't stable from one version to another of rustc, so we only # test that on one version - os: ubuntu-18.04 rust: 1.34.0 features: '' extra_args: '' - os: ubuntu-18.04 rust: 1.34.0 features: '' extra_args: 'compile_test -- --ignored' - os: ubuntu-18.04 rust: 1.34.0 features: 'use_core' extra_args: '' - os: ubuntu-18.04 rust: 1.34.0 features: 'use_core' extra_args: 'compile_test -- --ignored' steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.rust }} override: true - uses: actions-rs/cargo@v1 env: RUST_BACKTRACE: 1 with: command: test args: --features=${{ matrix.features }} ${{ matrix.extra_args }} - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable - run: cargo +stable install mdbook --no-default-features --features search --vers "^0.4.0" - run: mdbook build - run: mdbook test -L ./target/debug/deps/ if: ${{ matrix.features }} != 'use_core' clippy: name: Clippy runs-on: ubuntu-latest strategy: matrix: rust: - 1.34.0 - stable features: - '' - 'use_core' steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.rust }} override: true - run: rustup component add clippy - uses: actions-rs/cargo@v1 with: command: clippy args: --all-targets --features=${{ matrix.features }} -- -D warningsderivative-2.2.0/.gitignore010064400362620024044000000000461400305350200140650ustar0000000000000000target Cargo.lock /book /node_modules derivative-2.2.0/CHANGELOG.md010064400362620024044000000053141400305350200137110ustar0000000000000000# Change Log All notable changes to this project will be documented in this file. ## 2.2.0 * Add support for deriving traits on `repr(packed)` types ([#84]). * Fix bug with `Debug` bounds ([#83]). * Migrate documentation to `mdbook` and fix issues found in examples ([#83]). ## 2.1.3 * Fix Clippy warning ([#81]). ## 2.1.2 * Fix bug when used in combination with other attributes ([#79]). ## 2.1.1 * Improve error reporting. ([#70]) * Fix a Clippy warning in generated code. ([#71]). ## 2.1.0 * `feature_allow_slow_enum` is not required anymore on `enum` with `PartialEq`. ([#64]) * `PartialEq` generates more efficient code for C-like `enum`. ([#65]) * Fix issue with deriving `Hash` on generic `enums` #68. ([#68]) ## 2.0.2 * Fix a bug with `format_with` on `Debug` derives with generic types with trait bounds. ## 2.0.1 * Fix a hygiene bug with `Debug`. ([#60]) ## 2.0.0 This release should be compatible with version 1.*, but now requires rustc version 1.34 or later. * Update `syn`, `quote`, and `proc-macro2` dependencies. ([#59]) ## 1.0.4 This is the last version to support rustc versions 1.15 to 1.33. * Implement `PartialOrd` and `Ord` deriving. ## 1.0.3 * Do not require `syn`'s `full` feature anymore. ([#38], [#45]) * Fix an issue with using `#[derivative(Debug(format_with = "…"))]` on non-generic types. ([#40]) * Fix some warnings in the library with recent versions of `rustc`. * Fix some `clippy::pedantic` warnings in generated code. ([#46]) ## 1.0.2 * Add `use_core` feature to make `Derivative` usable in `core` crates. ## 1.0.1 * Updated `syn` to `0.15`. ([#25]) * Updated `quote` to `0.6`. ([#25]) ## 1.0.0 * Make stable. ## 0.3.1 * Fix a warning in `derivative(Debug)`. * Remove all `feature`s, this makes the crate usable on `beta`. [#25]: https://github.com/mcarton/rust-derivative/issues/25 [#38]: https://github.com/mcarton/rust-derivative/pull/38 [#40]: https://github.com/mcarton/rust-derivative/pull/40 [#45]: https://github.com/mcarton/rust-derivative/pull/45 [#46]: https://github.com/mcarton/rust-derivative/pull/46 [#59]: https://github.com/mcarton/rust-derivative/pull/59 [#60]: https://github.com/mcarton/rust-derivative/pull/60 [#61]: https://github.com/mcarton/rust-derivative/pull/61 [#64]: https://github.com/mcarton/rust-derivative/pull/64 [#65]: https://github.com/mcarton/rust-derivative/pull/65 [#68]: https://github.com/mcarton/rust-derivative/pull/68 [#70]: https://github.com/mcarton/rust-derivative/pull/70 [#71]: https://github.com/mcarton/rust-derivative/pull/71 [#79]: https://github.com/mcarton/rust-derivative/pull/79 [#81]: https://github.com/mcarton/rust-derivative/pull/81 [#83]: https://github.com/mcarton/rust-derivative/pull/83 [#84]: https://github.com/mcarton/rust-derivative/pull/84derivative-2.2.0/CONTRIBUTING.md010064400362620024044000000011751400305350200143320ustar0000000000000000Contributions are welcome! There are several ways you can contribute: * Submit ideas and feature requests on the [issue tracker]. * File bug reports on the [issue tracker]. Include as much details as you can and, ideally, a self-contained example if you can make one. * Improve the [documentation]. It consists of markdown files in the [doc](doc) directory. It uses [mdBook] to generate the website. * Implement something, fix bugs, etc. You know the deal. [documentation]: https://mcarton.github.io/rust-derivative/ [mdBook]: https://rust-lang.github.io/mdBook/ [issue tracker]: https://github.com/mcarton/rust-derivative/issues derivative-2.2.0/Cargo.toml.orig010064400362620024044000000012551400305350200147670ustar0000000000000000[package] name = "derivative" version = "2.2.0" authors = ["mcarton "] license = "MIT/Apache-2.0" readme = "README.md" documentation = "https://mcarton.github.io/rust-derivative/" repository = "https://github.com/mcarton/rust-derivative" description = "A set of alternative `derive` attributes for Rust" keywords = ["derive", "macro", "macro1-1", "plugin"] categories = ["rust-patterns"] [lib] proc-macro = true [dependencies] proc-macro2 = "1.0" quote = "1.0" syn = { version = "1.0.3", features = ["visit", "extra-traits"] } [dev-dependencies] # 1.0.23 requires rustc 1.36, while our msrv is 1.34 trybuild = "1.0.18, <1.0.23" [features] use_core = [] derivative-2.2.0/Cargo.toml0000644000000022640000000000000112400ustar00# 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 believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "derivative" version = "2.2.0" authors = ["mcarton "] description = "A set of alternative `derive` attributes for Rust" documentation = "https://mcarton.github.io/rust-derivative/" readme = "README.md" keywords = ["derive", "macro", "macro1-1", "plugin"] categories = ["rust-patterns"] license = "MIT/Apache-2.0" repository = "https://github.com/mcarton/rust-derivative" [lib] proc-macro = true [dependencies.proc-macro2] version = "1.0" [dependencies.quote] version = "1.0" [dependencies.syn] version = "1.0.3" features = ["visit", "extra-traits"] [dev-dependencies.trybuild] version = "1.0.18, <1.0.23" [features] use_core = [] derivative-2.2.0/LICENSE-APACHE010064400362620024044000000251371400305350200140310ustar0000000000000000 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 APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. derivative-2.2.0/LICENSE-MIT010064400362620024044000000020411400305350200135260ustar0000000000000000Copyright (c) 2016 Martin Carton Permission 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. derivative-2.2.0/README.md010064400362620024044000000033751400305350200133640ustar0000000000000000# Derivative [![Crates.io](https://img.shields.io/crates/v/derivative.svg?maxAge=3600)](https://crates.io/crates/derivative) [![Crates.io](https://img.shields.io/crates/l/derivative.svg?maxAge=3600)](https://github.com/mcarton/rust-derivative#license) ![Continuous integration](https://github.com/mcarton/rust-derivative/workflows/Continuous%20integration/badge.svg) This crate provides a set of alternative customizable `#[derive]` attributes for Rust. ## [Documentation][documentation] ## Stability This crate is stable and follows semver. It requires *rustc 1.34 or later* and changing the minimal rustc version will be considered a semver breaking change. ## What it does ```rust #[derive(Derivative)] #[derivative(Debug)] struct Foo { foo: u8, #[derivative(Debug="ignore")] bar: u8, } // Prints `Foo { foo: 42 }` println!("{:?}", Foo { foo: 42, bar: 1 }); ``` Check the [documentation] for more! ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or ) * MIT license ([LICENSE-MIT](LICENSE-MIT) or ) at your option. ## Acknowledgements This is inspired from how [`serde`] wonderfully handles attributes. This also takes some code and ideas from `serde` itself. Some tests are directly adapted from `rustc`'s tests. ## Contribution 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. [`serde`]: https://crates.io/crates/serde [documentation]: https://mcarton.github.io/rust-derivative/latest/index.html [rustc]: https://github.com/rust-lang/rust derivative-2.2.0/book.toml010064400362620024044000000003761400305350200137320ustar0000000000000000[book] title = "Derivative" src = "doc" [rust] edition = "2018" [build] create-missing = false [output.html.search] limit-results = 15 [output.html] additional-css = ["doc/custom.css"] git-repository-url = "https://github.com/mcarton/rust-derivative"derivative-2.2.0/doc/Clone.md010064400362620024044000000031031400305350200142210ustar0000000000000000# Custom attributes The `Copy` and `Clone` traits support the following attributes: * **Container attributes** * [`(bound="")`](#custom-bound) * [`Clone(clone_from="true")`](#clone-from) * **Field attributes** * [`(bound="")`](#custom-bound) # `clone_from` The [`Clone`] trait has a default implementation for [`clone_from`] and `derive(Clone)` never implements that method. *derivative* can implement it if asked explicitly. Note that while the generated implementation is good for structures, it might not be very efficient for enumerations. What it does is check if both `self` and the clone-from value have the same variant, if they have, use `clone_from` on the members, otherwise fallback to `*self = other.clone();`. Ask yourself if you really need this. # Custom bound As most other traits, `Copy` and `Debug` support a custom bound on container and fields. See [`Debug`'s documentation](Debug.md#custom-bound) for more information. # Limitations *rustc* can optimize `derive(Clone, Copy)` to generate faster, smaller code. So does *derivative*. But *rustc* does not know about `derivative(Copy)` and would not optimize `#[derivative(Copy)] #[derive(Clone)]`. To avoid that issue, you should avoid deriving `Clone` using *rustc*'s default `derive` and `Copy` using `derivative`. *derivative* will error if it detects that, but can't always do it. [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html [`clone_from`]: https://doc.rust-lang.org/std/clone/trait.Clone.html#method.clone_from derivative-2.2.0/doc/Debug.md010064400362620024044000000076461400305350200142270ustar0000000000000000# Custom attributes The `Debug` trait supports the following attributes: * **Container attributes** * [`Debug(bound="")`](#custom-bound) * [`Debug="transparent"`](#hiding-newtypes) * **Variant attributes** * [`Debug="transparent"`](#hiding-newtypes) * **Field attributes** * [`Debug(bound="")`](#custom-bound) * [`Debug(format_with="")`](#format-with) * [`Debug="ignore"`](#ignoring-a-field) # Ignoring a field You can use *derivative* to hide fields from a structure or enumeration `Debug` implementation: ```rust # extern crate derivative; # use derivative::Derivative; #[derive(Derivative)] #[derivative(Debug)] struct Foo { foo: u8, #[derivative(Debug="ignore")] bar: u8, } println!("{:?}", Foo { foo: 42, bar: 1 }); // Foo { foo: 42 } ``` # Hiding newtypes You can use *derivative* to automatically unwrap newtypes and enumeration variants with only one field: ```rust # extern crate derivative; # use derivative::Derivative; #[derive(Derivative)] #[derivative(Debug="transparent")] struct A(isize); #[derive(Derivative)] #[derivative(Debug)] enum C { Foo(u8), #[derivative(Debug="transparent")] Bar(u8), } println!("{:?}", A(42)); // 42 println!("{:?}", C::Bar(42)); // 42 // But: println!("{:?}", C::Foo(42)); // Foo(42) ``` # Format with You can pass a field to a format function: ```rust # extern crate derivative; # use derivative::Derivative; # mod path { # pub struct SomeTypeThatMightNotBeDebug; # pub mod to { # pub fn my_fmt_fn(_: &super::SomeTypeThatMightNotBeDebug, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { unimplemented!() } # } # } # use path::SomeTypeThatMightNotBeDebug; #[derive(Derivative)] #[derivative(Debug)] struct Foo { foo: u32, #[derivative(Debug(format_with="path::to::my_fmt_fn"))] bar: SomeTypeThatMightNotBeDebug, } ``` The field `bar` will be displayed with `path::to::my_fmt_fn(&bar, &mut fmt)` where `fmt` is the current [`Formatter`]. The function must the following prototype: ```rust,ignore fn fmt(&T, &mut std::fmt::Formatter) -> Result<(), std::fmt::Error>; ``` # Custom bound Usually, *derivative* will add a `T: Debug` bound for each type parameter `T` of the current type. If you do not want that, you can specify an explicit bound: * Either on the type. This replaces all bounds: ```rust # extern crate derivative; # use derivative::Derivative; # trait MyDebug { # fn my_fmt(&self, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error>; # } # use std::fmt::Debug; #[derive(Derivative)] #[derivative(Debug(bound="T: Debug, U: MyDebug"))] struct Foo { foo: T, #[derivative(Debug(format_with="MyDebug::my_fmt"))] bar: U, } ``` * Or on a field. This replaces the bound *derivative* guessed for that field. The example below is equivalent to the above: ```rust # extern crate derivative; # use derivative::Derivative; # trait MyDebug { # fn my_fmt(&self, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error>; # } #[derive(Derivative)] #[derivative(Debug)] struct Foo { foo: T, #[derivative(Debug(format_with="MyDebug::my_fmt", bound="U: MyDebug"))] bar: U, } ``` With `bound=""` it is possible to remove any bound for the type. This is useful if your type contains a `Foo` that is `Debug` even if `T` is not. [`Formatter`]: https://doc.rust-lang.org/std/fmt/struct.Formatter.html # Packed structures You can use *derivative* to implement `Debug` on packed structures. Unlike the standard `derive(debug)`, *derivative* does not require the structure itself to be `Copy`, but like the standard `derive(debug)`, it requires each (non-ignored) field to be `Copy`. ```rust # extern crate derivative; # use derivative::Derivative; #[derive(Derivative)] #[derivative(Debug)] #[repr(C, packed)] struct Foo { foo: u8, // `String` isn't `Copy` so it must be ignored to derive `Debug` #[derivative(Debug="ignore")] bar: String, } ```derivative-2.2.0/doc/Default.md010064400362620024044000000050121400305350200145460ustar0000000000000000# Custom attributes The `Default` trait supports the following attributes: * **Container attributes** * [`Default(bound="")`](#custom-bound) * [`Default="new"`](#new-function) * **Variant attributes** * [`Default`](#default-enumeration) * **Field attributes** * [`Default(bound="")`](#custom-bound) * [`Default(value="")`](#setting-the-value-of-a-field) # Default enumeration You can use *derivative* to derive a default implementation on enumerations! This does not work with *rustc*'s `#[derive(Default)]`. All you need is to specify what variant is the default value: ```rust # extern crate derivative; # use derivative::Derivative; #[derive(Debug, Derivative)] #[derivative(Default)] enum Enum { A, #[derivative(Default)] B, } println!("{:?}", Enum::default()); // B ``` # Setting the value of a field You can use *derivative* to change the default value of a field in a `Default` implementation: ```rust # extern crate derivative; # use derivative::Derivative; #[derive(Debug, Derivative)] #[derivative(Default)] struct Foo { foo: u8, #[derivative(Default(value="42"))] bar: u8, } println!("{:?}", Foo::default()); // Foo { foo: 0, bar: 42 } ``` # `new` function You can use *derivative* to derive a convenience `new` method for your type that calls `Default::default`: ```rust # extern crate derivative; # use derivative::Derivative; #[derive(Debug, Derivative)] #[derivative(Default(new="true"))] struct Foo { foo: u8, bar: u8, } println!("{:?}", Foo::new()); // Foo { foo: 0, bar: 0 } ``` # Custom bound The following does not work because `derive` adds a `T: Default` bound on the `impl Default for Foo`: ```rust,compile_fail # extern crate derivative; # use derivative::Derivative; #[derive(Default)] struct Foo { foo: Option, } struct NonDefault; Foo::::default(); // gives: // error: no associated item named `default` found for type `Foo` in the current scope // = note: the method `default` exists but the following trait bounds were not satisfied: `NonDefault : std::default::Default` ``` That bound however is useless as `Option: Default` for any `T`. `derivative` allows you to explicitly specify a bound if the inferred one is not correct: ```rust # extern crate derivative; # use derivative::Derivative; #[derive(Derivative)] #[derivative(Default(bound=""))] // don't need any bound struct Foo { foo: Option, } struct NonDefault; Foo::::default(); // works! ``` derivative-2.2.0/doc/Hash.md010064400362620024044000000041041400305350200140460ustar0000000000000000# Custom attributes The `Hash` trait supports the following attributes: * **Container attributes** * [`Hash(bound="")`](#custom-bound) * **Field attributes** * [`Hash(bound="")`](#custom-bound) * [`Hash(hash_with="")`](#hash-with) * [`Hash="ignore"`](#ignoring-a-field) # Ignoring a field You can use *derivative* to ignore fields from a `Hash` implementation: ```rust # extern crate derivative; # use derivative::Derivative; #[derive(Derivative)] #[derivative(Hash)] struct Foo { foo: u8, #[derivative(Hash="ignore")] bar: i32, } #[derive(Hash)] struct Bar { foo: u8, } # fn hash(t: &T) -> u64 { # use std::hash::Hasher; # let mut s = std::collections::hash_map::DefaultHasher::new(); # t.hash(&mut s); # s.finish() # } # assert_eq!(hash(&Foo { foo: 42, bar: -1337 }), hash(&Bar { foo: 42 })); ``` # Hash with You can pass a field to a hash function: ```rust # extern crate derivative; # use derivative::Derivative; # mod path { # pub struct SomeTypeThatMightNotBeHash; # pub mod to { # pub fn my_hash_fn(_: &super::SomeTypeThatMightNotBeHash, state: &mut H) where H: std::hash::Hasher { unimplemented!() } # } # } # use path::SomeTypeThatMightNotBeHash; #[derive(Derivative)] #[derivative(Hash)] struct Foo { foo: u32, #[derivative(Hash(hash_with="path::to::my_hash_fn"))] bar: SomeTypeThatMightNotBeHash, } ``` The field `bar` will be hashed with `path::to::my_hash_fn(&bar, &mut state)` where `state` is the current [`Hasher`]. The function must the following prototype: ```rust,ignore fn my_hash_fn(&T, state: &mut H) where H: Hasher; ``` # Limitations On structure, `derivative(Hash)` will produce the same hash as `derive(Hash)`. On unions however, it will produces the same hashes *only for unitary variants*! # Custom bound As most other traits, `Hash` supports a custom bound on container and fields. See [`Debug`'s documentation](Debug.md#custom-bound) for more information. [`Hasher`]: https://doc.rust-lang.org/std/hash/trait.Hasher.html derivative-2.2.0/doc/README.md010064400362620024044000000037401400305350200141250ustar0000000000000000# Derivative This crate provides a set of alternative `#[derive]` attributes for Rust. ## Examples *derivative* uses attributes to make it possible to derive more implementations than the built-in `derive(Trait)`. Here are a few examples of stuffs you cannot just `derive`. You can derive `Default` on enumerations:
With *derivative* [Original][default-value-source]
{{#playground default-enum.rs}} {{#playground default-enum-orig.rs}}
You can use different default values for some fields:
With *derivative* [Original][default-value-source]
{{#playground default-value.rs}} {{#playground default-value-orig.rs}}
Want a transparent `Debug` implementation for your wrapper? We got that:
With *derivative* [Original][transparent-source]
{{#playground debug-transparent.rs}} {{#playground debug-transparent-orig.rs}}
Need to ignore a field? We got that too:
With *derivative* [Original][eq-ignore-source]
{{#playground eq-ignore.rs}} {{#playground eq-ignore-orig.rs}}
[default-value-source]: https://github.com/rust-lang-nursery/regex/blob/3cfef1e79d135a3e8a670aff53e7fabef453a3e1/src/re_builder.rs#L12-L39 [default-enum-source]: https://github.com/rust-lang/rust/blob/16eeeac783d2ede28e09f2a433c612dea309fe33/src/libcore/option.rs#L714-L718 [transparent-source]: https://github.com/rust-lang/rust/blob/5457c35ece57bbc4a65baff239a02d6abb81c8a2/src/libcore/num/mod.rs#L46-L54 [eq-ignore-source]: https://github.com/steveklabnik/semver/blob/baa0fbb57c80a7fb344fbeedac24a28439ddf5b5/src/version.rs#L196-L205 derivative-2.2.0/doc/SUMMARY.md010064400362620024044000000022771400305350200143310ustar0000000000000000# Summary * [Overview](README.md) * [`Copy` and `Clone` traits](Clone.md) * [`Debug` trait](Debug.md) * [`Default` trait](Default.md) * [`Hash` trait](Hash.md) * [Comparison traits](cmp.md) derivative-2.2.0/doc/cmp.md010064400362620024044000000073121400305350200137460ustar0000000000000000# Custom attributes The `PartialEq`, `Eq`, `PartialOrd` and `Eq` and traits support the following attributes: * **Container attributes** * [`(bound="")`](#custom-bound) * **Field attributes** * [`(bound="")`](#custom-bound) The `PartialEq`, `PartialOrd` and `Ord` traits also supports the following attributes: * **Container attributes** * [`="feature_allow_slow_enum"`](#enumerations) * **Field attributes** * [`="ignore"`](#ignoring-a-field) * [`(compare_with="")`](#compare-with) (These attributes are not relevant for `Eq` which is just a marker trait.) # Enumerations Unfortunately, there is no way for derivative to derive `PartialOrd` or `Ord` on enumerations as efficiently as the built-in `derive(…)` yet. If you want to use derivative on enumerations anyway, you can add ```rust,ignore #[derivative(PartialOrd="feature_allow_slow_enum")] ``` to your enumeration. This acts as a “feature-gate”. This attribute is also allowed for `PartialEq` for historical reason. It is not necessary anymore as of v2.1.0. It was never necessary nor allowed for `Eq`. # Ignoring a field You can use *derivative* to ignore a field when comparing: ```rust # extern crate derivative; # use derivative::Derivative; #[derive(Derivative)] #[derivative(PartialEq)] struct Foo { foo: u8, #[derivative(PartialEq="ignore")] bar: u8, } assert!(Foo { foo: 0, bar: 42 } == Foo { foo: 0, bar: 7}); assert!(Foo { foo: 42, bar: 0 } != Foo { foo: 7, bar: 0}); ``` # Compare with Usually fields are compared using `==`, `PartialOrd::partial_cmp` or `Ord::cmp`. You can use an alternative comparison function if you like: ```rust # extern crate derivative; # use derivative::Derivative; # mod path { # pub struct SomeTypeThatMightNotBePartialEq; # pub mod to { # pub fn my_cmp_fn(_: &super::SomeTypeThatMightNotBePartialEq, _: &super::SomeTypeThatMightNotBePartialEq) -> bool { false } # } # } # use path::SomeTypeThatMightNotBePartialEq; #[derive(Derivative)] #[derivative(PartialEq)] struct Foo { foo: u32, #[derivative(PartialEq(compare_with="path::to::my_cmp_fn"))] bar: SomeTypeThatMightNotBePartialEq, } ``` `foo` will be compared with `==` and `bar` will be compared with `path::to::my_cmp_fn` which must have the following prototype: | Trait | Signature | |--------------|-----------| | `PartialEq` | `fn my_cmp_fn(&T, &T) -> bool;` | `PartialOrd` | `fn my_cmp_fn(&T, &T) -> std::option::Option;` | `Ord` | `fn my_cmp_fn(&T, &T) -> std::cmp::Ordering;` # Custom bound Usually if you derive `CmpTrait`, a `T: CmpTrait` bound is added for each type parameter `T`. You can use override this behavior if the inferred bound is not correct for you. Eg. comparing raw pointers does not require the type to be `Eq`, so you could use: ```rust # extern crate derivative; # use derivative::Derivative; #[derive(Derivative)] #[derivative(PartialEq)] struct WithPtr { #[derivative(PartialEq(bound=""))] foo: *const T } ``` See [`Default`'s documentation](./Default.md#custom-bound) for more details. # Packed structures You can use *derivative* to implement the comparison traits on packed structures. Unlike the standard `derive`, *derivative* does not require the structure itself to be `Copy`, but like the standard `derive`, it requires each (non-ignored) field to be `Copy`. ```rust # extern crate derivative; # use derivative::Derivative; #[derive(Derivative)] #[derivative(PartialEq)] #[repr(C, packed)] struct Foo { f: u32, #[derivative(PartialEq = "ignore")] t: String, } ```derivative-2.2.0/doc/custom.css010064400362620024044000000005611400305350200146700ustar0000000000000000#content > main > table { position: relative; left: 50%; transform: translateX(-50%); margin-left: 0px; margin-right: 0px; } #content > main > table td { vertical-align: top; } #content > main > table .hljs { background: none; } .readme-example { background: #f1f1f1; } table .readme-example > td { border: 1px hsl(0, 0%, 0%) solid; }derivative-2.2.0/doc/debug-transparent-orig.rs010064400362620024044000000002711400305350200175730ustar0000000000000000# use std::fmt; pub struct Wrapping(pub T); impl fmt::Debug for Wrapping { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) } }derivative-2.2.0/doc/debug-transparent.rs010064400362620024044000000002201400305350200166270ustar0000000000000000# extern crate derivative; # use derivative::Derivative; #[derive(Derivative)] #[derivative(Debug="transparent")] pub struct Wrapping(pub T);derivative-2.2.0/doc/default-enum-orig.rs010064400362620024044000000004631400305350200165370ustar0000000000000000# #![no_implicit_prelude] # extern crate core; # use core::default::Default; # use Option::None; # pub enum Option { /// No value None, /// Some value `T` Some(T), } impl Default for Option { /// Returns None. #[inline] fn default() -> Option { None } } derivative-2.2.0/doc/default-enum.rs010064400362620024044000000003401400305350200155730ustar0000000000000000# extern crate derivative; # use derivative::Derivative; #[derive(Derivative)] #[derivative(Default(bound=""))] pub enum Option { #[derivative(Default)] /// No value None, /// Some value `T` Some(T), }derivative-2.2.0/doc/default-value-orig.rs010064400362620024044000000012771400305350200167130ustar0000000000000000pub struct RegexOptions { pub pats: Vec, pub size_limit: usize, pub dfa_size_limit: usize, pub case_insensitive: bool, pub multi_line: bool, pub dot_matches_new_line: bool, pub swap_greed: bool, pub ignore_whitespace: bool, pub unicode: bool, } impl Default for RegexOptions { fn default() -> Self { RegexOptions { pats: vec![], size_limit: 10 * (1 << 20), dfa_size_limit: 2 * (1 << 20), case_insensitive: false, multi_line: false, dot_matches_new_line: false, swap_greed: false, ignore_whitespace: false, unicode: true, } } }derivative-2.2.0/doc/default-value.rs010064400362620024044000000010241400305350200157430ustar0000000000000000# extern crate derivative; # use derivative::Derivative; #[derive(Derivative)] #[derivative(Default)] pub struct RegexOptions { pub pats: Vec, #[derivative(Default(value="10 * (1 << 20)"))] pub size_limit: usize, #[derivative(Default(value="2 * (1 << 20)"))] pub dfa_size_limit: usize, pub case_insensitive: bool, pub multi_line: bool, pub dot_matches_new_line: bool, pub swap_greed: bool, pub ignore_whitespace: bool, #[derivative(Default(value="true"))] pub unicode: bool, }derivative-2.2.0/doc/eq-ignore-orig.rs010064400362620024044000000021161400305350200160340ustar0000000000000000# use std::{cmp, hash}; # #[derive(PartialEq, Hash)] # struct Identifier; pub struct Version { /// The major version. pub major: u64, /// The minor version. pub minor: u64, /// The patch version. pub patch: u64, /// The pre-release version identifier. pub pre: Vec, /// The build metadata, ignored when /// determining version precedence. pub build: Vec, } impl cmp::PartialEq for Version { #[inline] fn eq(&self, other: &Version) -> bool { // We should ignore build metadata // here, otherwise versions v1 and // v2 can exist such that !(v1 < v2) // && !(v1 > v2) && v1 != v2, which // violate strict total ordering rules. self.major == other.major && self.minor == other.minor && self.patch == other.patch && self.pre == other.pre } } impl hash::Hash for Version { fn hash(&self, into: &mut H) { self.major.hash(into); self.minor.hash(into); self.patch.hash(into); self.pre.hash(into); } }derivative-2.2.0/doc/eq-ignore.rs010064400362620024044000000014201400305350200150730ustar0000000000000000# extern crate derivative; # use derivative::Derivative; # #[derive(PartialEq, Hash)] # struct Identifier; #[derive(Derivative)] #[derivative(PartialEq, Hash)] pub struct Version { /// The major version. pub major: u64, /// The minor version. pub minor: u64, /// The patch version. pub patch: u64, /// The pre-release version identifier. pub pre: Vec, // We should ignore build metadata // here, otherwise versions v1 and // v2 can exist such that !(v1 < v2) // && !(v1 > v2) && v1 != v2, which // violate strict total ordering rules. #[derivative(PartialEq="ignore")] #[derivative(Hash="ignore")] /// The build metadata, ignored when /// determining version precedence. pub build: Vec, }derivative-2.2.0/doc/styles/website.css010064400362620024044000000002041400305350200163350ustar0000000000000000code .hljs-meta { color: #969896 } code .hljs-meta-string { color: #183691 } code .hljs-title { color: #a71d5d !important } derivative-2.2.0/src/ast.rs010064400362620024044000000103051400305350200140200ustar0000000000000000use attr; use proc_macro2; use syn; use syn::spanned::Spanned as SynSpanned; #[derive(Debug)] pub struct Input<'a> { pub attrs: attr::Input, pub body: Body<'a>, pub generics: &'a syn::Generics, pub ident: syn::Ident, pub span: proc_macro2::Span, } #[derive(Debug)] pub enum Body<'a> { Enum(Vec>), Struct(Style, Vec>), } #[derive(Debug)] pub struct Variant<'a> { pub attrs: attr::Input, pub fields: Vec>, pub ident: syn::Ident, pub style: Style, } #[derive(Debug)] pub struct Field<'a> { pub attrs: attr::Field, pub ident: Option, pub ty: &'a syn::Type, pub span: proc_macro2::Span, } #[derive(Clone, Copy, Debug)] pub enum Style { Struct, Tuple, Unit, } impl<'a> Input<'a> { pub fn from_ast( item: &'a syn::DeriveInput, errors: &mut proc_macro2::TokenStream, ) -> Result, ()> { let attrs = attr::Input::from_ast(&item.attrs, errors)?; let body = match item.data { syn::Data::Enum(syn::DataEnum { ref variants, .. }) => { Body::Enum(enum_from_ast(variants, errors)?) } syn::Data::Struct(syn::DataStruct { ref fields, .. }) => { let (style, fields) = struct_from_ast(fields, errors)?; Body::Struct(style, fields) } syn::Data::Union(..) => { errors.extend( syn::Error::new_spanned(item, "derivative does not support unions") .to_compile_error(), ); return Err(()); } }; Ok(Input { attrs, body, generics: &item.generics, ident: item.ident.clone(), span: item.span(), }) } /// Checks whether this type is an enum with only unit variants. pub fn is_trivial_enum(&self) -> bool { match &self.body { Body::Enum(e) => e.iter().all(|v| v.is_unit()), Body::Struct(..) => false, } } } impl<'a> Body<'a> { pub fn all_fields(&self) -> Vec<&Field> { match *self { Body::Enum(ref variants) => variants .iter() .flat_map(|variant| variant.fields.iter()) .collect(), Body::Struct(_, ref fields) => fields.iter().collect(), } } pub fn is_empty(&self) -> bool { match *self { Body::Enum(ref variants) => variants.is_empty(), Body::Struct(_, ref fields) => fields.is_empty(), } } } impl<'a> Variant<'a> { /// Checks whether this variant is a unit variant. pub fn is_unit(&self) -> bool { self.fields.is_empty() } } fn enum_from_ast<'a>( variants: &'a syn::punctuated::Punctuated, errors: &mut proc_macro2::TokenStream, ) -> Result>, ()> { variants .iter() .map(|variant| { let (style, fields) = struct_from_ast(&variant.fields, errors)?; Ok(Variant { attrs: attr::Input::from_ast(&variant.attrs, errors)?, fields, ident: variant.ident.clone(), style, }) }) .collect() } fn struct_from_ast<'a>( fields: &'a syn::Fields, errors: &mut proc_macro2::TokenStream, ) -> Result<(Style, Vec>), ()> { match *fields { syn::Fields::Named(ref fields) => { Ok((Style::Struct, fields_from_ast(&fields.named, errors)?)) } syn::Fields::Unnamed(ref fields) => { Ok((Style::Tuple, fields_from_ast(&fields.unnamed, errors)?)) } syn::Fields::Unit => Ok((Style::Unit, Vec::new())), } } fn fields_from_ast<'a>( fields: &'a syn::punctuated::Punctuated, errors: &mut proc_macro2::TokenStream, ) -> Result>, ()> { fields .iter() .map(|field| { Ok(Field { attrs: attr::Field::from_ast(field, errors)?, ident: field.ident.clone(), ty: &field.ty, span: field.span(), }) }) .collect() } derivative-2.2.0/src/attr.rs010064400362620024044000000743631400305350200142210ustar0000000000000000use proc_macro2; use syn; use syn::spanned::Spanned; /// Represent the `derivative` attributes on the input type (`struct`/`enum`). #[derive(Debug, Default)] pub struct Input { /// Whether `Clone` is present and its specific attributes. pub clone: Option, /// Whether `Copy` is present and its specific attributes. pub copy: Option, /// Whether `Debug` is present and its specific attributes. pub debug: Option, /// Whether `Default` is present and its specific attributes. pub default: Option, /// Whether `Eq` is present and its specific attributes. pub eq: Option, /// Whether `Hash` is present and its specific attributes. pub hash: Option, /// Whether `PartialEq` is present and its specific attributes. pub partial_eq: Option, /// Whether `PartialOrd` is present and its specific attributes. pub partial_ord: Option, /// Whether `Ord` is present and its specific attributes. pub ord: Option, pub is_packed: bool, } #[derive(Debug, Default)] /// Represent the `derivative` attributes on a field. pub struct Field { /// The parameters for `Clone`. clone: FieldClone, /// The parameters for `Copy`. copy_bound: Option>, /// The parameters for `Debug`. debug: FieldDebug, /// The parameters for `Default`. default: FieldDefault, /// The parameters for `Eq`. eq_bound: Option>, /// The parameters for `Hash`. hash: FieldHash, /// The parameters for `PartialEq`. partial_eq: FieldPartialEq, /// The parameters for `PartialOrd`. partial_ord: FieldPartialOrd, /// The parameters for `Ord`. ord: FieldOrd, } #[derive(Debug, Default)] /// Represent the `derivative(Clone(…))` attributes on an input. pub struct InputClone { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, /// Whether the implementation should have an explicit `clone_from`. pub clone_from: bool, } #[derive(Debug, Default)] /// Represent the `derivative(Clone(…))` attributes on an input. pub struct InputCopy { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, } #[derive(Debug, Default)] /// Represent the `derivative(Debug(…))` attributes on an input. pub struct InputDebug { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, /// Whether the type is marked `transparent`. pub transparent: bool, } #[derive(Debug, Default)] /// Represent the `derivative(Default(…))` attributes on an input. pub struct InputDefault { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, /// Whether the type is marked with `new`. pub new: bool, } #[derive(Debug, Default)] /// Represent the `derivative(Eq(…))` attributes on an input. pub struct InputEq { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, } #[derive(Debug, Default)] /// Represent the `derivative(Hash(…))` attributes on an input. pub struct InputHash { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, } #[derive(Debug, Default)] /// Represent the `derivative(PartialEq(…))` attributes on an input. pub struct InputPartialEq { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, } #[derive(Debug, Default)] /// Represent the `derivative(PartialOrd(…))` attributes on an input. pub struct InputPartialOrd { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, /// Allow `derivative(PartialOrd)` on enums: on_enum: bool, } #[derive(Debug, Default)] /// Represent the `derivative(Ord(…))` attributes on an input. pub struct InputOrd { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, /// Allow `derivative(Ord)` on enums: on_enum: bool, } #[derive(Debug, Default)] /// Represents the `derivative(Clone(…))` attributes on a field. pub struct FieldClone { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, /// The `clone_with` attribute if present and the path to the cloning function. clone_with: Option, } #[derive(Debug, Default)] /// Represents the `derivative(Debug(…))` attributes on a field. pub struct FieldDebug { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, /// The `format_with` attribute if present and the path to the formatting function. format_with: Option, /// Whether the field is to be ignored from output. ignore: bool, } #[derive(Debug, Default)] /// Represent the `derivative(Default(…))` attributes on a field. pub struct FieldDefault { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, /// The default value for the field if present. pub value: Option, } #[derive(Debug, Default)] /// Represents the `derivative(Hash(…))` attributes on a field. pub struct FieldHash { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, /// The `hash_with` attribute if present and the path to the hashing function. hash_with: Option, /// Whether the field is to be ignored when hashing. ignore: bool, } #[derive(Debug, Default)] /// Represent the `derivative(PartialEq(…))` attributes on a field. pub struct FieldPartialEq { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, /// The `compare_with` attribute if present and the path to the comparison function. compare_with: Option, /// Whether the field is to be ignored when comparing. ignore: bool, } #[derive(Debug, Default)] /// Represent the `derivative(PartialOrd(…))` attributes on a field. pub struct FieldPartialOrd { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, /// The `compare_with` attribute if present and the path to the comparison function. compare_with: Option, /// Whether the field is to be ignored when comparing. ignore: bool, } #[derive(Debug, Default)] /// Represent the `derivative(Ord(…))` attributes on a field. pub struct FieldOrd { /// The `bound` attribute if present and the corresponding bounds. bounds: Option>, /// The `compare_with` attribute if present and the path to the comparison function. compare_with: Option, /// Whether the field is to be ignored when comparing. ignore: bool, } macro_rules! for_all_attr { ($errors:ident; for ($name:ident, $value:ident) in $attrs:expr; $($body:tt)*) => { for meta_items in $attrs.iter() { let meta_items = derivative_attribute(meta_items, $errors); if let Some(meta_items) = meta_items { for meta_item in meta_items.iter() { let meta_item = read_items(meta_item, $errors); let MetaItem($name, $value) = try!(meta_item); match $name.to_string().as_ref() { $($body)* } } } } }; } macro_rules! match_attributes { ($errors:ident for $trait:expr; let Some($name:ident) = $unwrapped:expr; for $value:ident in $values:expr; $($body:tt)* ) => { let mut $name = $unwrapped.take().unwrap_or_default(); match_attributes! { $errors for $trait; for $value in $values; $($body)* } $unwrapped = Some($name); }; ($errors:ident for $trait:expr; for $value:ident in $values:expr; $($body:tt)* ) => { for (name, $value) in $values { match name { Some(ident) => { match ident.to_string().as_ref() { $($body)* unknown => { let message = format!("Unknown attribute `{}` for trait `{}`", unknown, $trait); $errors.extend(quote_spanned! {ident.span()=> compile_error!(#message); }); } } } None => { let value = $value.expect("Expected value to be passed"); match value.value().as_ref() { $($body)* unknown => { let message = format!("Unknown attribute `{}` for trait `{}`", unknown, $trait); let span = value.span(); $errors.extend(quote_spanned! {span=> compile_error!(#message); }); } } } } } }; } impl Input { /// Parse the `derivative` attributes on a type. #[allow(clippy::cognitive_complexity)] // mostly macros pub fn from_ast( attrs: &[syn::Attribute], errors: &mut proc_macro2::TokenStream, ) -> Result { let mut input = Input { is_packed: attrs.iter().any(has_repr_packed_attr), ..Default::default() }; for_all_attr! { errors; for (name, values) in attrs; "Clone" => { match_attributes! { errors for "Clone"; let Some(clone) = input.clone; for value in values; "bound" => parse_bound(&mut clone.bounds, value, errors), "clone_from" => { clone.clone_from = parse_boolean_meta_item(value, true, "clone_from", errors); } } } "Copy" => { match_attributes! { errors for "Copy"; let Some(copy) = input.copy; for value in values; "bound" => parse_bound(&mut copy.bounds, value, errors), } } "Debug" => { match_attributes! { errors for "Debug"; let Some(debug) = input.debug; for value in values; "bound" => parse_bound(&mut debug.bounds, value, errors), "transparent" => { debug.transparent = parse_boolean_meta_item(value, true, "transparent", errors); } } } "Default" => { match_attributes! { errors for "Default"; let Some(default) = input.default; for value in values; "bound" => parse_bound(&mut default.bounds, value, errors), "new" => { default.new = parse_boolean_meta_item(value, true, "new", errors); } } } "Eq" => { match_attributes! { errors for "Eq"; let Some(eq) = input.eq; for value in values; "bound" => parse_bound(&mut eq.bounds, value, errors), } } "Hash" => { match_attributes! { errors for "Hash"; let Some(hash) = input.hash; for value in values; "bound" => parse_bound(&mut hash.bounds, value, errors), } } "PartialEq" => { match_attributes! { errors for "PartialEq"; let Some(partial_eq) = input.partial_eq; for value in values; "bound" => parse_bound(&mut partial_eq.bounds, value, errors), "feature_allow_slow_enum" => (), // backward compatibility, now unnecessary } } "PartialOrd" => { match_attributes! { errors for "PartialOrd"; let Some(partial_ord) = input.partial_ord; for value in values; "bound" => parse_bound(&mut partial_ord.bounds, value, errors), "feature_allow_slow_enum" => { partial_ord.on_enum = parse_boolean_meta_item(value, true, "feature_allow_slow_enum", errors); } } } "Ord" => { match_attributes! { errors for "Ord"; let Some(ord) = input.ord; for value in values; "bound" => parse_bound(&mut ord.bounds, value, errors), "feature_allow_slow_enum" => { ord.on_enum = parse_boolean_meta_item(value, true, "feature_allow_slow_enum", errors); } } } unknown => { let message = format!("deriving `{}` is not supported by derivative", unknown); errors.extend(quote_spanned! {name.span()=> compile_error!(#message); }); } } Ok(input) } pub fn clone_bound(&self) -> Option<&[syn::WherePredicate]> { self.clone .as_ref() .and_then(|d| d.bounds.as_ref().map(Vec::as_slice)) } pub fn clone_from(&self) -> bool { self.clone.as_ref().map_or(false, |d| d.clone_from) } pub fn copy_bound(&self) -> Option<&[syn::WherePredicate]> { self.copy .as_ref() .and_then(|d| d.bounds.as_ref().map(Vec::as_slice)) } pub fn debug_bound(&self) -> Option<&[syn::WherePredicate]> { self.debug .as_ref() .and_then(|d| d.bounds.as_ref().map(Vec::as_slice)) } pub fn debug_transparent(&self) -> bool { self.debug.as_ref().map_or(false, |d| d.transparent) } pub fn default_bound(&self) -> Option<&[syn::WherePredicate]> { self.default .as_ref() .and_then(|d| d.bounds.as_ref().map(Vec::as_slice)) } pub fn eq_bound(&self) -> Option<&[syn::WherePredicate]> { self.eq .as_ref() .and_then(|d| d.bounds.as_ref().map(Vec::as_slice)) } pub fn hash_bound(&self) -> Option<&[syn::WherePredicate]> { self.hash .as_ref() .and_then(|d| d.bounds.as_ref().map(Vec::as_slice)) } pub fn partial_eq_bound(&self) -> Option<&[syn::WherePredicate]> { self.partial_eq .as_ref() .and_then(|d| d.bounds.as_ref().map(Vec::as_slice)) } pub fn partial_ord_bound(&self) -> Option<&[syn::WherePredicate]> { self.partial_ord .as_ref() .and_then(|d| d.bounds.as_ref().map(Vec::as_slice)) } pub fn ord_bound(&self) -> Option<&[syn::WherePredicate]> { self.ord .as_ref() .and_then(|d| d.bounds.as_ref().map(Vec::as_slice)) } pub fn partial_ord_on_enum(&self) -> bool { self.partial_ord.as_ref().map_or(false, |d| d.on_enum) } pub fn ord_on_enum(&self) -> bool { self.ord.as_ref().map_or(false, |d| d.on_enum) } } impl Field { /// Parse the `derivative` attributes on a type. #[allow(clippy::cognitive_complexity)] // mostly macros pub fn from_ast( field: &syn::Field, errors: &mut proc_macro2::TokenStream, ) -> Result { let mut out = Field::default(); for_all_attr! { errors; for (name, values) in field.attrs; "Clone" => { match_attributes! { errors for "Clone"; for value in values; "bound" => parse_bound(&mut out.clone.bounds, value, errors), "clone_with" => { let path = value.expect("`clone_with` needs a value"); out.clone.clone_with = parse_str_lit(&path, errors).ok(); } } } "Debug" => { match_attributes! { errors for "Debug"; for value in values; "bound" => parse_bound(&mut out.debug.bounds, value, errors), "format_with" => { let path = value.expect("`format_with` needs a value"); out.debug.format_with = parse_str_lit(&path, errors).ok(); } "ignore" => { out.debug.ignore = parse_boolean_meta_item(value, true, "ignore", errors); } } } "Default" => { match_attributes! { errors for "Default"; for value in values; "bound" => parse_bound(&mut out.default.bounds, value, errors), "value" => { let value = value.expect("`value` needs a value"); out.default.value = parse_str_lit(&value, errors).ok(); } } } "Eq" => { match_attributes! { errors for "Eq"; for value in values; "bound" => parse_bound(&mut out.eq_bound, value, errors), } } "Hash" => { match_attributes! { errors for "Hash"; for value in values; "bound" => parse_bound(&mut out.hash.bounds, value, errors), "hash_with" => { let path = value.expect("`hash_with` needs a value"); out.hash.hash_with = parse_str_lit(&path, errors).ok(); } "ignore" => { out.hash.ignore = parse_boolean_meta_item(value, true, "ignore", errors); } } } "PartialEq" => { match_attributes! { errors for "PartialEq"; for value in values; "bound" => parse_bound(&mut out.partial_eq.bounds, value, errors), "compare_with" => { let path = value.expect("`compare_with` needs a value"); out.partial_eq.compare_with = parse_str_lit(&path, errors).ok(); } "ignore" => { out.partial_eq.ignore = parse_boolean_meta_item(value, true, "ignore", errors); } } } "PartialOrd" => { match_attributes! { errors for "PartialOrd"; for value in values; "bound" => parse_bound(&mut out.partial_ord.bounds, value, errors), "compare_with" => { let path = value.expect("`compare_with` needs a value"); out.partial_ord.compare_with = parse_str_lit(&path, errors).ok(); } "ignore" => { out.partial_ord.ignore = parse_boolean_meta_item(value, true, "ignore", errors); } } } "Ord" => { match_attributes! { errors for "Ord"; for value in values; "bound" => parse_bound(&mut out.ord.bounds, value, errors), "compare_with" => { let path = value.expect("`compare_with` needs a value"); out.ord.compare_with = parse_str_lit(&path, errors).ok(); } "ignore" => { out.ord.ignore = parse_boolean_meta_item(value, true, "ignore", errors); } } } unknown => { let message = format!("deriving `{}` is not supported by derivative", unknown); errors.extend(quote_spanned! {name.span()=> compile_error!(#message); }); } } Ok(out) } pub fn clone_bound(&self) -> Option<&[syn::WherePredicate]> { self.clone.bounds.as_ref().map(Vec::as_slice) } pub fn clone_with(&self) -> Option<&syn::Path> { self.clone.clone_with.as_ref() } pub fn copy_bound(&self) -> Option<&[syn::WherePredicate]> { self.copy_bound.as_ref().map(Vec::as_slice) } pub fn debug_bound(&self) -> Option<&[syn::WherePredicate]> { self.debug.bounds.as_ref().map(Vec::as_slice) } pub fn debug_format_with(&self) -> Option<&syn::Path> { self.debug.format_with.as_ref() } pub fn ignore_debug(&self) -> bool { self.debug.ignore } pub fn ignore_hash(&self) -> bool { self.hash.ignore } pub fn default_bound(&self) -> Option<&[syn::WherePredicate]> { self.default.bounds.as_ref().map(Vec::as_slice) } pub fn default_value(&self) -> Option<&proc_macro2::TokenStream> { self.default.value.as_ref() } pub fn eq_bound(&self) -> Option<&[syn::WherePredicate]> { self.eq_bound.as_ref().map(Vec::as_slice) } pub fn hash_bound(&self) -> Option<&[syn::WherePredicate]> { self.hash.bounds.as_ref().map(Vec::as_slice) } pub fn hash_with(&self) -> Option<&syn::Path> { self.hash.hash_with.as_ref() } pub fn partial_eq_bound(&self) -> Option<&[syn::WherePredicate]> { self.partial_eq.bounds.as_ref().map(Vec::as_slice) } pub fn partial_ord_bound(&self) -> Option<&[syn::WherePredicate]> { self.partial_ord.bounds.as_ref().map(Vec::as_slice) } pub fn ord_bound(&self) -> Option<&[syn::WherePredicate]> { self.ord.bounds.as_ref().map(Vec::as_slice) } pub fn partial_eq_compare_with(&self) -> Option<&syn::Path> { self.partial_eq.compare_with.as_ref() } pub fn partial_ord_compare_with(&self) -> Option<&syn::Path> { self.partial_ord.compare_with.as_ref() } pub fn ord_compare_with(&self) -> Option<&syn::Path> { self.ord.compare_with.as_ref() } pub fn ignore_partial_eq(&self) -> bool { self.partial_eq.ignore } pub fn ignore_partial_ord(&self) -> bool { self.partial_ord.ignore } pub fn ignore_ord(&self) -> bool { self.ord.ignore } } /// Represent an attribute. /// /// We only have a limited set of possible attributes: /// /// * `#[derivative(Debug)]` is represented as `(Debug, [])`; /// * `#[derivative(Debug="foo")]` is represented as `(Debug, [(None, Some("foo"))])`; /// * `#[derivative(Debug(foo="bar")]` is represented as `(Debug, [(Some(foo), Some("bar"))])`. struct MetaItem<'a>( &'a syn::Ident, Vec<(Option<&'a syn::Ident>, Option<&'a syn::LitStr>)>, ); /// Parse an arbitrary item for our limited `MetaItem` subset. fn read_items<'a>(item: &'a syn::NestedMeta, errors: &mut proc_macro2::TokenStream) -> Result, ()> { let item = match *item { syn::NestedMeta::Meta(ref item) => item, syn::NestedMeta::Lit(ref lit) => { errors.extend(quote_spanned! {lit.span()=> compile_error!("expected meta-item but found literal"); }); return Err(()); } }; match *item { syn::Meta::Path(ref path) => match path.get_ident() { Some(name) => Ok(MetaItem(name, Vec::new())), None => { errors.extend(quote_spanned! {path.span()=> compile_error!("expected derivative attribute to be a string, but found a path"); }); Err(()) } }, syn::Meta::List(syn::MetaList { ref path, nested: ref values, .. }) => { let values = values .iter() .map(|value| { if let syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue { ref path, lit: ref value, .. })) = *value { let (name, value) = ensure_str_lit(&path, &value, errors)?; Ok((Some(name), Some(value))) } else { errors.extend(quote_spanned! {value.span()=> compile_error!("expected named value"); }); Err(()) } }) .collect::>()?; let name = match path.get_ident() { Some(name) => name, None => { errors.extend(quote_spanned! {path.span()=> compile_error!("expected derivative attribute to be a string, but found a path"); }); return Err(()); } }; Ok(MetaItem(name, values)) } syn::Meta::NameValue(syn::MetaNameValue { ref path, lit: ref value, .. }) => { let (name, value) = ensure_str_lit(&path, &value, errors)?; Ok(MetaItem(name, vec![(None, Some(value))])) } } } /// Filter the `derivative` items from an attribute. fn derivative_attribute( attribute: &syn::Attribute, errors: &mut proc_macro2::TokenStream, ) -> Option> { if !attribute.path.is_ident("derivative") { return None; } match attribute.parse_meta() { Ok(syn::Meta::List(meta_list)) => Some(meta_list.nested), Ok(_) => None, Err(e) => { let message = format!("invalid attribute: {}", e); errors.extend(quote_spanned! {e.span()=> compile_error!(#message); }); None } } } /// Parse an item value as a boolean. Accepted values are the string literal `"true"` and /// `"false"`. The `default` parameter specifies what the value of the boolean is when only its /// name is specified (eg. `Debug="ignore"` is equivalent to `Debug(ignore="true")`). The `name` /// parameter is used for error reporting. fn parse_boolean_meta_item( item: Option<&syn::LitStr>, default: bool, name: &str, errors: &mut proc_macro2::TokenStream, ) -> bool { if let Some(item) = item.as_ref() { match item.value().as_ref() { "true" => true, "false" => false, val => { if val == name { true } else { let message = format!( r#"expected `"true"` or `"false"` for `{}`, got `{}`"#, name, val ); errors.extend(quote_spanned! {item.span()=> compile_error!(#message); }); default } } } } else { default } } /// Parse a `bound` item. fn parse_bound( opt_bounds: &mut Option>, value: Option<&syn::LitStr>, errors: &mut proc_macro2::TokenStream, ) { let bound = value.expect("`bound` needs a value"); let bound_value = bound.value(); *opt_bounds = if !bound_value.is_empty() { let where_string = syn::LitStr::new(&format!("where {}", bound_value), bound.span()); let bounds = parse_str_lit::(&where_string, errors) .map(|wh| wh.predicates.into_iter().collect()); match bounds { Ok(bounds) => Some(bounds), Err(_) => { errors.extend(quote_spanned! {where_string.span()=> compile_error!("could not parse bound"); }); None } } } else { Some(vec![]) }; } fn parse_str_lit(value: &syn::LitStr, errors: &mut proc_macro2::TokenStream) -> Result where T: syn::parse::Parse, { match value.parse() { Ok(value) => Ok(value), Err(e) => { let message = format!("could not parse string literal: {}", e); errors.extend(quote_spanned! {value.span()=> compile_error!(#message); }); Err(()) } } } fn ensure_str_lit<'a>( attr_path: &'a syn::Path, lit: &'a syn::Lit, errors: &mut proc_macro2::TokenStream, ) -> Result<(&'a syn::Ident, &'a syn::LitStr), ()> { let attr_name = match attr_path.get_ident() { Some(attr_name) => attr_name, None => { errors.extend(quote_spanned! {attr_path.span()=> compile_error!("expected derivative attribute to be a string, but found a path"); }); return Err(()); } }; if let syn::Lit::Str(ref lit) = *lit { Ok((attr_name, lit)) } else { let message = format!( "expected derivative {} attribute to be a string: `{} = \"...\"`", attr_name, attr_name ); errors.extend(quote_spanned! {lit.span()=> compile_error!(#message); }); Err(()) } } pub fn has_repr_packed_attr(attr: &syn::Attribute) -> bool { if let Ok(attr) = attr.parse_meta() { if attr.path().get_ident().map(|i| i == "repr") == Some(true) { if let syn::Meta::List(items) = attr { for item in items.nested { if let syn::NestedMeta::Meta(item) = item { if item.path().get_ident().map(|i| i == "packed") == Some(true) { return true; } } } } } } false } derivative-2.2.0/src/bound.rs010064400362620024044000000123001400305350200143350ustar0000000000000000/* This file incorporates work covered by the following copyright and * permission notice: * Copyright 2016 The serde Developers. See * https://github.com/serde-rs/serde/blob/3f28a9324042950afa80354722aeeee1a55cbfa3/README.md#license. * * Licensed under the Apache License, Version 2.0 or the MIT license * , at your * option. This file may not be copied, modified, or distributed * except according to those terms. */ use ast; use attr; use std::collections::HashSet; use syn::{self, visit, GenericParam}; // use internals::ast::Item; // use internals::attr; /// Remove the default from every type parameter because in the generated `impl`s /// they look like associated types: "error: associated type bindings are not /// allowed here". pub fn without_defaults(generics: &syn::Generics) -> syn::Generics { syn::Generics { params: generics .params .iter() .map(|generic_param| match *generic_param { GenericParam::Type(ref ty_param) => syn::GenericParam::Type(syn::TypeParam { default: None, ..ty_param.clone() }), ref param => param.clone(), }) .collect(), ..generics.clone() } } pub fn with_where_predicates( generics: &syn::Generics, predicates: &[syn::WherePredicate], ) -> syn::Generics { let mut cloned = generics.clone(); cloned .make_where_clause() .predicates .extend(predicates.iter().cloned()); cloned } pub fn with_where_predicates_from_fields( item: &ast::Input, generics: &syn::Generics, from_field: F, ) -> syn::Generics where F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>, { let mut cloned = generics.clone(); { let fields = item.body.all_fields(); let field_where_predicates = fields .iter() .flat_map(|field| from_field(&field.attrs)) .flat_map(|predicates| predicates.to_vec()); cloned .make_where_clause() .predicates .extend(field_where_predicates); } cloned } /// Puts the given bound on any generic type parameters that are used in fields /// for which filter returns true. /// /// For example, the following structure needs the bound `A: Debug, B: Debug`. /// /// ```ignore /// struct S<'b, A, B: 'b, C> { /// a: A, /// b: Option<&'b B> /// #[derivative(Debug="ignore")] /// c: C, /// } /// ``` pub fn with_bound( item: &ast::Input, generics: &syn::Generics, filter: F, bound: &syn::Path, ) -> syn::Generics where F: Fn(&attr::Field) -> bool, { #[derive(Debug)] struct FindTyParams { /// Set of all generic type parameters on the current struct (A, B, C in /// the example). Initialized up front. all_ty_params: HashSet, /// Set of generic type parameters used in fields for which filter /// returns true (A and B in the example). Filled in as the visitor sees /// them. relevant_ty_params: HashSet, } impl<'ast> visit::Visit<'ast> for FindTyParams { fn visit_path(&mut self, path: &'ast syn::Path) { if is_phantom_data(path) { // Hardcoded exception, because `PhantomData` implements // most traits whether or not `T` implements it. return; } if path.leading_colon.is_none() && path.segments.len() == 1 { let id = &path.segments[0].ident; if self.all_ty_params.contains(id) { self.relevant_ty_params.insert(id.clone()); } } visit::visit_path(self, path); } } let all_ty_params: HashSet<_> = generics .type_params() .map(|ty_param| ty_param.ident.clone()) .collect(); let relevant_tys = item .body .all_fields() .into_iter() .filter(|field| { if let syn::Type::Path(syn::TypePath { ref path, .. }) = *field.ty { !is_phantom_data(path) } else { true } }) .filter(|field| filter(&field.attrs)) .map(|field| &field.ty); let mut visitor = FindTyParams { all_ty_params, relevant_ty_params: HashSet::new(), }; for ty in relevant_tys { visit::visit_type(&mut visitor, ty); } let mut cloned = generics.clone(); { let relevant_where_predicates = generics .type_params() .map(|ty_param| &ty_param.ident) .filter(|id| visitor.relevant_ty_params.contains(id)) .map(|id| -> syn::WherePredicate { parse_quote!( #id : #bound ) }); cloned .make_where_clause() .predicates .extend(relevant_where_predicates); } cloned } #[allow(clippy::match_like_matches_macro)] // needs rustc 1.42 fn is_phantom_data(path: &syn::Path) -> bool { match path.segments.last() { Some(path) if path.ident == "PhantomData" => true, _ => false, } } derivative-2.2.0/src/clone.rs010064400362620024044000000142671400305350200143440ustar0000000000000000use proc_macro2; use ast; use attr; use matcher; use syn; use utils; /// Derive `Copy` for `input`. pub fn derive_copy(input: &ast::Input) -> proc_macro2::TokenStream { let name = &input.ident; let copy_trait_path = copy_trait_path(); let generics = utils::build_impl_generics( input, ©_trait_path, |attrs| attrs.copy_bound().is_none(), |field| field.copy_bound(), |input| input.copy_bound(), ); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); quote! { #[allow(unused_qualifications)] impl #impl_generics #copy_trait_path for #name #ty_generics #where_clause {} } } /// Derive `Clone` for `input`. pub fn derive_clone(input: &ast::Input) -> proc_macro2::TokenStream { let name = &input.ident; let clone_trait_path = clone_trait_path(); let generics = utils::build_impl_generics( input, &clone_trait_path, needs_clone_bound, |field| field.clone_bound(), |input| input.clone_bound(), ); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let is_copy = input.attrs.copy.is_some(); if is_copy && input.generics.type_params().count() == 0 { quote! { #[allow(unused_qualifications)] impl #impl_generics #clone_trait_path for #name #ty_generics #where_clause { fn clone(&self) -> Self { *self } } } } else { let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed).build_arms( input, "__arg", |arm_path, _, _, style, _, bis| { let field_clones = bis.iter().map(|bi| { let arg = &bi.expr; let clone = if let Some(clone_with) = bi.field.attrs.clone_with() { quote!(#clone_with(&#arg)) } else { quote!(#arg.clone()) }; if let Some(ref name) = bi.field.ident { quote! { #name: #clone } } else { clone } }); match style { ast::Style::Struct => { quote! { #arm_path { #(#field_clones),* } } } ast::Style::Tuple => { quote! { #arm_path (#(#field_clones),*) } } ast::Style::Unit => { quote! { #arm_path } } } }, ); let clone_from = if input.attrs.clone_from() { Some( matcher::Matcher::new(matcher::BindingStyle::RefMut, input.attrs.is_packed).build_arms( input, "__arg", |outer_arm_path, _, _, _, _, outer_bis| { let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed).build_arms( input, "__other", |inner_arm_path, _, _, _, _, inner_bis| { if outer_arm_path == inner_arm_path { let field_clones = outer_bis.iter().zip(inner_bis).map( |(outer_bi, inner_bi)| { let outer = &outer_bi.expr; let inner = &inner_bi.expr; quote!(#outer.clone_from(&#inner);) }, ); quote! { #(#field_clones)* return; } } else { quote!() } }, ); quote! { match *other { #body } } }, ), ) } else { None }; let clone_from = clone_from.map(|body| { // Enumerations are only cloned-from if both variants are the same. // If they are different, fallback to normal cloning. let fallback = if let ast::Body::Enum(_) = input.body { Some(quote!(*self = other.clone();)) } else { None }; quote! { #[allow(clippy::needless_return)] fn clone_from(&mut self, other: &Self) { match *self { #body } #fallback } } }); quote! { #[allow(unused_qualifications)] impl #impl_generics #clone_trait_path for #name #ty_generics #where_clause { fn clone(&self) -> Self { match *self { #body } } #clone_from } } } } fn needs_clone_bound(attrs: &attr::Field) -> bool { attrs.clone_bound().is_none() } /// Return the path of the `Clone` trait, that is `::std::clone::Clone`. fn clone_trait_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::clone::Clone) } else { parse_quote!(::std::clone::Clone) } } /// Return the path of the `Copy` trait, that is `::std::marker::Copy`. fn copy_trait_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::marker::Copy) } else { parse_quote!(::std::marker::Copy) } } derivative-2.2.0/src/cmp.rs010064400362620024044000000343571400305350200140250ustar0000000000000000// https://github.com/rust-lang/rust/issues/13101 use ast; use attr; use matcher; use paths; use proc_macro2; use syn; use utils; /// Derive `Eq` for `input`. pub fn derive_eq(input: &ast::Input) -> proc_macro2::TokenStream { let name = &input.ident; let eq_trait_path = eq_trait_path(); let generics = utils::build_impl_generics( input, &eq_trait_path, needs_eq_bound, |field| field.eq_bound(), |input| input.eq_bound(), ); let new_where_clause; let (impl_generics, ty_generics, mut where_clause) = generics.split_for_impl(); if let Some(new_where_clause2) = maybe_add_copy(input, where_clause, |f| !f.attrs.ignore_partial_eq()) { new_where_clause = new_where_clause2; where_clause = Some(&new_where_clause); } quote! { #[allow(unused_qualifications)] impl #impl_generics #eq_trait_path for #name #ty_generics #where_clause {} } } /// Derive `PartialEq` for `input`. pub fn derive_partial_eq(input: &ast::Input) -> proc_macro2::TokenStream { let discriminant_cmp = if let ast::Body::Enum(_) = input.body { let discriminant_path = paths::discriminant_path(); quote!((#discriminant_path(&*self) == #discriminant_path(&*other))) } else { quote!(true) }; let name = &input.ident; let partial_eq_trait_path = partial_eq_trait_path(); let generics = utils::build_impl_generics( input, &partial_eq_trait_path, needs_partial_eq_bound, |field| field.partial_eq_bound(), |input| input.partial_eq_bound(), ); let new_where_clause; let (impl_generics, ty_generics, mut where_clause) = generics.split_for_impl(); let match_fields = if input.is_trivial_enum() { quote!(true) } else { matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed) .with_field_filter(|f: &ast::Field| !f.attrs.ignore_partial_eq()) .build_2_arms( (quote!(*self), quote!(*other)), (input, "__self"), (input, "__other"), |_, _, _, (left_variant, right_variant)| { let cmp = left_variant.iter().zip(&right_variant).map(|(o, i)| { let outer_name = &o.expr; let inner_name = &i.expr; if o.field.attrs.ignore_partial_eq() { None } else if let Some(compare_fn) = o.field.attrs.partial_eq_compare_with() { Some(quote!(&& #compare_fn(&#outer_name, &#inner_name))) } else { Some(quote!(&& &#outer_name == &#inner_name)) } }); quote!(true #(#cmp)*) }, ) }; if let Some(new_where_clause2) = maybe_add_copy(input, where_clause, |f| !f.attrs.ignore_partial_eq()) { new_where_clause = new_where_clause2; where_clause = Some(&new_where_clause); } quote! { #[allow(unused_qualifications)] #[allow(clippy::unneeded_field_pattern)] impl #impl_generics #partial_eq_trait_path for #name #ty_generics #where_clause { fn eq(&self, other: &Self) -> bool { #discriminant_cmp && #match_fields } } } } /// Derive `PartialOrd` for `input`. pub fn derive_partial_ord( input: &ast::Input, errors: &mut proc_macro2::TokenStream, ) -> proc_macro2::TokenStream { if let ast::Body::Enum(_) = input.body { if !input.attrs.partial_ord_on_enum() { let message = "can't use `#[derivative(PartialOrd)]` on an enumeration without \ `feature_allow_slow_enum`; see the documentation for more details"; errors.extend(syn::Error::new(input.span, message).to_compile_error()); } } let option_path = option_path(); let ordering_path = ordering_path(); let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed) .with_field_filter(|f: &ast::Field| !f.attrs.ignore_partial_ord()) .build_arms(input, "__self", |_, n, _, _, _, outer_bis| { let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed) .with_field_filter(|f: &ast::Field| !f.attrs.ignore_partial_ord()) .build_arms(input, "__other", |_, m, _, _, _, inner_bis| { match n.cmp(&m) { ::std::cmp::Ordering::Less => { quote!(#option_path::Some(#ordering_path::Less)) } ::std::cmp::Ordering::Greater => { quote!(#option_path::Some(#ordering_path::Greater)) } ::std::cmp::Ordering::Equal => { let equal_path = quote!(#ordering_path::Equal); outer_bis .iter() .rev() .zip(inner_bis.into_iter().rev()) .fold(quote!(#option_path::Some(#equal_path)), |acc, (o, i)| { let outer_name = &o.expr; let inner_name = &i.expr; if o.field.attrs.ignore_partial_ord() { acc } else { let cmp_fn = o .field .attrs .partial_ord_compare_with() .map(|f| quote!(#f)) .unwrap_or_else(|| { let path = partial_ord_trait_path(); quote!(#path::partial_cmp) }); quote!(match #cmp_fn(&#outer_name, &#inner_name) { #option_path::Some(#equal_path) => #acc, __derive_ordering_other => __derive_ordering_other, }) } }) } } }); quote! { match *other { #body } } }); let name = &input.ident; let partial_ord_trait_path = partial_ord_trait_path(); let generics = utils::build_impl_generics( input, &partial_ord_trait_path, needs_partial_ord_bound, |field| field.partial_ord_bound(), |input| input.partial_ord_bound(), ); let new_where_clause; let (impl_generics, ty_generics, mut where_clause) = generics.split_for_impl(); if let Some(new_where_clause2) = maybe_add_copy(input, where_clause, |f| !f.attrs.ignore_partial_ord()) { new_where_clause = new_where_clause2; where_clause = Some(&new_where_clause); } quote! { #[allow(unused_qualifications)] #[allow(clippy::unneeded_field_pattern)] impl #impl_generics #partial_ord_trait_path for #name #ty_generics #where_clause { fn partial_cmp(&self, other: &Self) -> #option_path<#ordering_path> { match *self { #body } } } } } /// Derive `Ord` for `input`. pub fn derive_ord( input: &ast::Input, errors: &mut proc_macro2::TokenStream, ) -> proc_macro2::TokenStream { if let ast::Body::Enum(_) = input.body { if !input.attrs.ord_on_enum() { let message = "can't use `#[derivative(Ord)]` on an enumeration without \ `feature_allow_slow_enum`; see the documentation for more details"; errors.extend(syn::Error::new(input.span, message).to_compile_error()); } } let ordering_path = ordering_path(); let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed) .with_field_filter(|f: &ast::Field| !f.attrs.ignore_ord()) .build_arms(input, "__self", |_, n, _, _, _, outer_bis| { let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed) .with_field_filter(|f: &ast::Field| !f.attrs.ignore_ord()) .build_arms(input, "__other", |_, m, _, _, _, inner_bis| { match n.cmp(&m) { ::std::cmp::Ordering::Less => quote!(#ordering_path::Less), ::std::cmp::Ordering::Greater => quote!(#ordering_path::Greater), ::std::cmp::Ordering::Equal => { let equal_path = quote!(#ordering_path::Equal); outer_bis .iter() .rev() .zip(inner_bis.into_iter().rev()) .fold(quote!(#equal_path), |acc, (o, i)| { let outer_name = &o.expr; let inner_name = &i.expr; if o.field.attrs.ignore_ord() { acc } else { let cmp_fn = o .field .attrs .ord_compare_with() .map(|f| quote!(#f)) .unwrap_or_else(|| { let path = ord_trait_path(); quote!(#path::cmp) }); quote!(match #cmp_fn(&#outer_name, &#inner_name) { #equal_path => #acc, __derive_ordering_other => __derive_ordering_other, }) } }) } } }); quote! { match *other { #body } } }); let name = &input.ident; let ord_trait_path = ord_trait_path(); let generics = utils::build_impl_generics( input, &ord_trait_path, needs_ord_bound, |field| field.ord_bound(), |input| input.ord_bound(), ); let new_where_clause; let (impl_generics, ty_generics, mut where_clause) = generics.split_for_impl(); if let Some(new_where_clause2) = maybe_add_copy(input, where_clause, |f| !f.attrs.ignore_ord()) { new_where_clause = new_where_clause2; where_clause = Some(&new_where_clause); } quote! { #[allow(unused_qualifications)] #[allow(clippy::unneeded_field_pattern)] impl #impl_generics #ord_trait_path for #name #ty_generics #where_clause { fn cmp(&self, other: &Self) -> #ordering_path { match *self { #body } } } } } fn needs_partial_eq_bound(attrs: &attr::Field) -> bool { !attrs.ignore_partial_eq() && attrs.partial_eq_bound().is_none() } fn needs_partial_ord_bound(attrs: &attr::Field) -> bool { !attrs.ignore_partial_ord() && attrs.partial_ord_bound().is_none() } fn needs_ord_bound(attrs: &attr::Field) -> bool { !attrs.ignore_ord() && attrs.ord_bound().is_none() } fn needs_eq_bound(attrs: &attr::Field) -> bool { !attrs.ignore_partial_eq() && attrs.eq_bound().is_none() } /// Return the path of the `Eq` trait, that is `::std::cmp::Eq`. fn eq_trait_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::cmp::Eq) } else { parse_quote!(::std::cmp::Eq) } } /// Return the path of the `PartialEq` trait, that is `::std::cmp::PartialEq`. fn partial_eq_trait_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::cmp::PartialEq) } else { parse_quote!(::std::cmp::PartialEq) } } /// Return the path of the `PartialOrd` trait, that is `::std::cmp::PartialOrd`. fn partial_ord_trait_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::cmp::PartialOrd) } else { parse_quote!(::std::cmp::PartialOrd) } } /// Return the path of the `Ord` trait, that is `::std::cmp::Ord`. fn ord_trait_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::cmp::Ord) } else { parse_quote!(::std::cmp::Ord) } } /// Return the path of the `Option` trait, that is `::std::option::Option`. fn option_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::option::Option) } else { parse_quote!(::std::option::Option) } } /// Return the path of the `Ordering` trait, that is `::std::cmp::Ordering`. fn ordering_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::cmp::Ordering) } else { parse_quote!(::std::cmp::Ordering) } } fn maybe_add_copy( input: &ast::Input, where_clause: Option<&syn::WhereClause>, field_filter: impl Fn(&ast::Field) -> bool, ) -> Option { if input.attrs.is_packed && !input.body.is_empty() { let mut new_where_clause = where_clause.cloned().unwrap_or_else(|| syn::WhereClause { where_token: parse_quote!(where), predicates: Default::default(), }); new_where_clause.predicates.extend( input .body .all_fields() .into_iter() .filter(|f| field_filter(f)) .map(|f| { let ty = f.ty; let pred: syn::WherePredicate = parse_quote!(#ty: Copy); pred }), ); Some(new_where_clause) } else { None } } derivative-2.2.0/src/debug.rs010064400362620024044000000164461400305350200143330ustar0000000000000000use proc_macro2; use ast; use attr; use matcher; use syn; use syn::spanned::Spanned; use utils; pub fn derive(input: &ast::Input) -> proc_macro2::TokenStream { let debug_trait_path = debug_trait_path(); let fmt_path = fmt_path(); let formatter = quote_spanned! {input.span=> __f}; let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed) .with_field_filter(|f: &ast::Field| !f.attrs.ignore_debug()) .build_arms(input, "__arg", |_, _, arm_name, style, attrs, bis| { let field_prints = bis.iter().filter_map(|bi| { if bi.field.attrs.ignore_debug() { return None; } if attrs.debug_transparent() { return Some(quote_spanned! {arm_name.span()=> #debug_trait_path::fmt(__arg_0, #formatter) }); } let arg_expr = &bi.expr; let arg_ident = &bi.ident; let dummy_debug = bi.field.attrs.debug_format_with().map(|format_fn| { format_with( bi.field, &input.attrs.debug_bound(), &arg_expr, &arg_ident, format_fn, input.generics.clone(), ) }); let expr = if bi.field.attrs.debug_format_with().is_some() { quote_spanned! {arm_name.span()=> &#arg_ident } } else { quote_spanned! {arm_name.span()=> &&#arg_expr } }; let builder = if let Some(ref name) = bi.field.ident { let name = name.to_string(); quote_spanned! {arm_name.span()=> #dummy_debug let _ = __debug_trait_builder.field(#name, #expr); } } else { quote_spanned! {arm_name.span()=> #dummy_debug let _ = __debug_trait_builder.field(#expr); } }; Some(builder) }); let method = match style { ast::Style::Struct => "debug_struct", ast::Style::Tuple | ast::Style::Unit => "debug_tuple", }; let method = syn::Ident::new(method, proc_macro2::Span::call_site()); if attrs.debug_transparent() { quote_spanned! {arm_name.span()=> #(#field_prints)* } } else { let name = arm_name.to_string(); quote_spanned! {arm_name.span()=> let mut __debug_trait_builder = #formatter.#method(#name); #(#field_prints)* __debug_trait_builder.finish() } } }); let name = &input.ident; let generics = utils::build_impl_generics( input, &debug_trait_path, needs_debug_bound, |field| field.debug_bound(), |input| input.debug_bound(), ); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); // don't attach a span to prevent issue #58 let match_self = quote!(match *self); quote_spanned! {input.span=> #[allow(unused_qualifications)] #[allow(clippy::unneeded_field_pattern)] impl #impl_generics #debug_trait_path for #name #ty_generics #where_clause { fn fmt(&self, #formatter: &mut #fmt_path::Formatter) -> #fmt_path::Result { #match_self { #body } } } } } fn needs_debug_bound(attrs: &attr::Field) -> bool { !attrs.ignore_debug() && attrs.debug_bound().is_none() } /// Return the path of the `Debug` trait, that is `::std::fmt::Debug`. fn debug_trait_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::fmt::Debug) } else { parse_quote!(::std::fmt::Debug) } } /// Return the path of the `fmt` module, that is `::std::fmt`. fn fmt_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::fmt) } else { parse_quote!(::std::fmt) } } /// Return the path of the `PhantomData` type, that is `::std::marker::PhantomData`. fn phantom_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::marker::PhantomData) } else { parse_quote!(::std::marker::PhantomData) } } fn format_with( f: &ast::Field, bounds: &Option<&[syn::WherePredicate]>, arg_expr: &proc_macro2::TokenStream, arg_ident: &syn::Ident, format_fn: &syn::Path, mut generics: syn::Generics, ) -> proc_macro2::TokenStream { let debug_trait_path = debug_trait_path(); let fmt_path = fmt_path(); let phantom_path = phantom_path(); generics .make_where_clause() .predicates .extend(f.attrs.debug_bound().unwrap_or(&[]).iter().cloned()); generics .params .push(syn::GenericParam::Lifetime(syn::LifetimeDef::new( parse_quote!('_derivative), ))); let where_predicates = generics .type_params() .map(|ty| { let mut bounds = syn::punctuated::Punctuated::new(); bounds.push(syn::TypeParamBound::Lifetime(syn::Lifetime::new( "'_derivative", proc_macro2::Span::call_site(), ))); let path = syn::Path::from(syn::PathSegment::from(ty.ident.clone())); syn::WherePredicate::Type(syn::PredicateType { lifetimes: None, bounded_ty: syn::Type::Path(syn::TypePath { qself: None, path }), colon_token: Default::default(), bounds, }) }) .chain(bounds.iter().flat_map(|b| b.iter().cloned())) .collect::>(); generics .make_where_clause() .predicates .extend(where_predicates); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let ty = f.ty; // Leave off the type parameter bounds, defaults, and attributes let phantom = generics.type_params().map(|tp| &tp.ident); let mut ctor_generics = generics.clone(); *ctor_generics .lifetimes_mut() .last() .expect("There must be a '_derivative lifetime") = syn::LifetimeDef::new(parse_quote!('_)); let (_, ctor_ty_generics, _) = ctor_generics.split_for_impl(); let ctor_ty_generics = ctor_ty_generics.as_turbofish(); // don't attach a span to prevent issue #58 let match_self = quote!(match self.0); quote_spanned!(format_fn.span()=> let #arg_ident = { struct Dummy #impl_generics (&'_derivative #ty, #phantom_path <(#(#phantom,)*)>) #where_clause; impl #impl_generics #debug_trait_path for Dummy #ty_generics #where_clause { fn fmt(&self, __f: &mut #fmt_path::Formatter) -> #fmt_path::Result { #match_self { this => #format_fn(this, __f) } } } Dummy #ctor_ty_generics (&&#arg_expr, #phantom_path) }; ) } derivative-2.2.0/src/default.rs010064400362620024044000000070011400305350200146540ustar0000000000000000use proc_macro2; use ast; use attr; use syn; use utils; /// Derive `Default` for `input`. pub fn derive(input: &ast::Input, default: &attr::InputDefault) -> proc_macro2::TokenStream { fn make_variant_data( variant_name: &proc_macro2::TokenStream, style: ast::Style, fields: &[ast::Field], ) -> proc_macro2::TokenStream { let default_trait_path = default_trait_path(); match style { ast::Style::Struct => { let mut defaults = Vec::new(); for f in fields { let name = f .ident .as_ref() .expect("A structure field must have a name"); let default = f .attrs .default_value() .map_or_else(|| quote!(#default_trait_path::default()), |v| quote!(#v)); defaults.push(quote!(#name: #default)); } quote!(#variant_name { #(#defaults),* }) } ast::Style::Tuple => { let mut defaults = Vec::new(); for f in fields { let default = f .attrs .default_value() .map_or_else(|| quote!(#default_trait_path::default()), |v| quote!(#v)); defaults.push(default); } quote!(#variant_name ( #(#defaults),* )) } ast::Style::Unit => quote!(#variant_name), } } let name = &input.ident; let default_trait_path = default_trait_path(); let generics = utils::build_impl_generics( input, &default_trait_path, |attrs| attrs.default_bound().is_none(), |field| field.default_bound(), |input| input.default_bound(), ); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let body = match input.body { ast::Body::Enum(ref data) => { let arms = data.iter().filter_map(|variant| { if variant.attrs.default.is_some() { let vname = &variant.ident; Some(make_variant_data( "e!(#name::#vname), variant.style, &variant.fields, )) } else { None } }); quote!(#(#arms),*) } ast::Body::Struct(style, ref vd) => make_variant_data("e!(#name), style, vd), }; let new_fn = if default.new { Some(quote!( #[allow(unused_qualifications)] impl #impl_generics #name #ty_generics #where_clause { /// Creates a default value for this type. #[inline] pub fn new() -> Self { ::default() } } )) } else { None }; quote!( #new_fn #[allow(unused_qualifications)] impl #impl_generics #default_trait_path for #name #ty_generics #where_clause { fn default() -> Self { #body } } ) } /// Return the path of the `Default` trait, that is `::std::default::Default`. fn default_trait_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::default::Default) } else { parse_quote!(::std::default::Default) } } derivative-2.2.0/src/hash.rs010064400362620024044000000052501400305350200141570ustar0000000000000000use proc_macro2; use ast; use attr; use matcher; use paths; use syn; use utils; pub fn derive(input: &ast::Input) -> proc_macro2::TokenStream { let hasher_trait_path = hasher_trait_path(); let hash_trait_path = hash_trait_path(); let discriminant = if let ast::Body::Enum(_) = input.body { let discriminant = paths::discriminant_path(); Some(quote!( #hash_trait_path::hash(&#discriminant(self), __state); )) } else { None }; let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed).build_arms( input, "__arg", |_, _, _, _, _, bis| { let field_prints = bis.iter().filter_map(|bi| { if bi.field.attrs.ignore_hash() { return None; } let arg = &bi.expr; if let Some(hash_with) = bi.field.attrs.hash_with() { Some(quote! { #hash_with(&#arg, __state); }) } else { Some(quote! { #hash_trait_path::hash(&#arg, __state); }) } }); quote! { #(#field_prints)* } }, ); let name = &input.ident; let generics = utils::build_impl_generics( input, &hash_trait_path, needs_hash_bound, |field| field.hash_bound(), |input| input.hash_bound(), ); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let hasher_ty_parameter = utils::hygienic_type_parameter(input, "__H"); quote! { #[allow(unused_qualifications)] impl #impl_generics #hash_trait_path for #name #ty_generics #where_clause { fn hash<#hasher_ty_parameter>(&self, __state: &mut #hasher_ty_parameter) where #hasher_ty_parameter: #hasher_trait_path { #discriminant match *self { #body } } } } } fn needs_hash_bound(attrs: &attr::Field) -> bool { !attrs.ignore_hash() && attrs.hash_bound().is_none() } /// Return the path of the `Hash` trait, that is `::std::hash::Hash`. fn hash_trait_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::hash::Hash) } else { parse_quote!(::std::hash::Hash) } } /// Return the path of the `Hasher` trait, that is `::std::hash::Hasher`. fn hasher_trait_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::hash::Hasher) } else { parse_quote!(::std::hash::Hasher) } } derivative-2.2.0/src/lib.rs010064400362620024044000000050061400305350200140010ustar0000000000000000// We need to support Rust 1.34 to stable #![allow(deprecated)] #![allow(renamed_and_removed_lints)] // support for multiple Clippy versions #![allow(clippy::unknown_clippy_lints)] // because of other #![allow]s #![allow(clippy::mem_replace_with_default)] // needs rustc 1.40 #![allow(clippy::option_as_ref_deref)] // needs rustc 1.40 #![allow(clippy::cyclomatic_complexity)] // old name of cognitive_complexity #![allow(clippy::cognitive_complexity)] // in code generated by macros #![allow(clippy::redundant_closure)] extern crate proc_macro; extern crate proc_macro2; #[macro_use] extern crate syn; #[macro_use] extern crate quote; mod ast; mod attr; mod bound; mod clone; mod cmp; mod debug; mod default; mod hash; mod matcher; mod paths; mod utils; use proc_macro::TokenStream; fn derive_impls( input: &mut ast::Input, errors: &mut proc_macro2::TokenStream, ) -> proc_macro2::TokenStream { let mut tokens = proc_macro2::TokenStream::new(); if input.attrs.clone.is_some() { tokens.extend(clone::derive_clone(input)); } if input.attrs.copy.is_some() { tokens.extend(clone::derive_copy(input)); } if input.attrs.debug.is_some() { tokens.extend(debug::derive(input)); } if let Some(ref default) = input.attrs.default { tokens.extend(default::derive(input, default)); } if input.attrs.eq.is_some() { tokens.extend(cmp::derive_eq(input)); } if input.attrs.hash.is_some() { tokens.extend(hash::derive(input)); } if input.attrs.partial_eq.is_some() { tokens.extend(cmp::derive_partial_eq(input)); } if input.attrs.partial_ord.is_some() { tokens.extend(cmp::derive_partial_ord(input, errors)); } if input.attrs.ord.is_some() { tokens.extend(cmp::derive_ord(input, errors)); } tokens.extend(std::mem::replace( errors, Default::default(), )); tokens } #[cfg_attr(not(test), proc_macro_derive(Derivative, attributes(derivative)))] pub fn derivative(input: TokenStream) -> TokenStream { let mut errors = proc_macro2::TokenStream::new(); let mut output = match syn::parse::(input) { Ok(parsed) => { ast::Input::from_ast(&parsed, &mut errors) .map(|mut input| derive_impls(&mut input, &mut errors)) .unwrap_or_default() }, Err(error) => { errors.extend(error.to_compile_error()); Default::default() } }; output.extend(errors); output.into() }derivative-2.2.0/src/matcher.rs010064400362620024044000000242171400305350200146630ustar0000000000000000#![allow(dead_code)] // TODO: remove // This is inspired from `synstructure`, but `synstructure` is not adapted in severals ways // including: // * `&mut` everywhere // * not generic, we use our own `ast`, `synstructure` only knows about `syn` // * missing information (what arm are we in?, what attributes? etc.) use proc_macro2::{self, TokenStream}; use quote::ToTokens; use syn; use ast; use attr; use quote; /// The type of binding to use when generating a pattern. #[derive(Debug, Copy, Clone)] pub enum BindingStyle { /// `x` Move, /// `mut x` MoveMut, /// `ref x` Ref, /// `ref mut x` RefMut, } impl BindingStyle { fn with_packed(self, is_packed: bool) -> BindingStyle { match self { BindingStyle::Move | BindingStyle::MoveMut => self, BindingStyle::Ref if is_packed => BindingStyle::Move, BindingStyle::RefMut if is_packed => BindingStyle::MoveMut, BindingStyle::Ref | BindingStyle::RefMut => self, } } } impl quote::ToTokens for BindingStyle { fn to_tokens(&self, tokens: &mut TokenStream) { match *self { BindingStyle::Move => (), BindingStyle::MoveMut => tokens.extend(quote!(mut)), BindingStyle::Ref => tokens.extend(quote!(ref)), BindingStyle::RefMut => { tokens.extend(quote!(ref mut)); } } } } #[derive(Debug)] pub struct BindingInfo<'a> { pub expr: TokenStream, pub ident: syn::Ident, pub field: &'a ast::Field<'a>, } #[derive(Debug)] pub struct CommonVariant<'a> { path: syn::Path, name: &'a syn::Ident, style: ast::Style, attrs: &'a attr::Input, } pub struct Matcher { binding_name: String, binding_style: BindingStyle, is_packed: bool, field_filter: T, } impl Matcher bool> { pub fn new(style: BindingStyle, is_packed: bool) -> Self { Matcher { binding_name: "__arg".into(), binding_style: style.with_packed(is_packed), is_packed, field_filter: |_| true, } } } impl bool> Matcher { pub fn with_name(self, name: String) -> Self { Matcher { binding_name: name, ..self } } pub fn with_field_filter

(self, field_filter: P) -> Matcher

{ Matcher { field_filter, binding_name: self.binding_name, binding_style: self.binding_style, is_packed: self.is_packed, } } pub fn build_arms(self, input: &ast::Input, binding_name: &str, f: F) -> TokenStream where F: Fn( syn::Path, usize, &syn::Ident, ast::Style, &attr::Input, Vec, ) -> TokenStream, { let variants = self.build_match_pattern(input, binding_name); // Now that we have the patterns, generate the actual branches of the match // expression let mut t = TokenStream::new(); for (i, (variant, (pat, bindings))) in variants.into_iter().enumerate() { let body = f( variant.path, i, variant.name, variant.style, variant.attrs, bindings, ); quote!(#pat => { #body }).to_tokens(&mut t); } t } pub fn build_2_arms( self, (left_matched_expr, right_matched_expr): (TokenStream, TokenStream), left: (&ast::Input, &str), right: (&ast::Input, &str), f: F, ) -> TokenStream where F: Fn( usize, CommonVariant, CommonVariant, (Vec, Vec), ) -> TokenStream, { let left_variants = self.build_match_pattern(left.0, left.1); let right_variants = self.build_match_pattern(right.0, right.1); assert_eq!(left_variants.len(), right_variants.len()); if left_variants.len() == 1 { let (left, (left_pat, left_bindings)) = left_variants.into_iter().next().unwrap(); let (right, (right_pat, right_bindings)) = right_variants.into_iter().next().unwrap(); let body = f(0, left, right, (left_bindings, right_bindings)); quote! { match #left_matched_expr { #left_pat => match #right_matched_expr { #right_pat => #body, }, } } } else { // Now that we have the patterns, generate the actual branches of the match // expression let mut t = TokenStream::new(); for (i, (left, right)) in left_variants.into_iter().zip(right_variants).enumerate() { let (left, (left_pat, left_bindings)) = left; let (right, (right_pat, right_bindings)) = right; let body = f(i, left, right, (left_bindings, right_bindings)); quote!((#left_pat, #right_pat) => { #body }).to_tokens(&mut t); } quote! { match (&#left_matched_expr, &#right_matched_expr) { #t _ => unreachable!(), } } } } /// Generate patterns for matching against all of the variants pub fn build_match_pattern<'a>( &self, input: &'a ast::Input, binding_name: &str, ) -> Vec<(CommonVariant<'a>, (TokenStream, Vec>))> { let ident = &input.ident; match input.body { ast::Body::Enum(ref variants) => variants .iter() .map(|variant| { let variant_ident = &variant.ident; let path = parse_quote!(#ident::#variant_ident); let pat = self.build_match_pattern_impl( &path, variant.style, &variant.fields, binding_name, ); ( CommonVariant { path, name: variant_ident, style: variant.style, attrs: &variant.attrs, }, pat, ) }) .collect(), ast::Body::Struct(style, ref vd) => { let path = parse_quote!(#ident); vec![( CommonVariant { path, name: ident, style, attrs: &input.attrs, }, self.build_match_pattern_impl(ident, style, vd, binding_name), )] } } } fn build_match_pattern_impl<'a, N>( &self, name: &N, style: ast::Style, fields: &'a [ast::Field<'a>], binding_name: &str, ) -> (TokenStream, Vec>) where N: quote::ToTokens, { let (stream, matches) = match style { ast::Style::Unit => (TokenStream::new(), Vec::new()), ast::Style::Tuple => { let (stream, matches) = fields.iter().enumerate().fold( (TokenStream::new(), Vec::new()), |(stream, matches), field| { self.build_inner_pattern( (stream, matches), field, binding_name, |f, ident, binding| { if (self.field_filter)(f) { quote!(#binding #ident ,) } else { quote!(_ ,) } }, ) }, ); (quote! { ( #stream ) }, matches) } ast::Style::Struct => { let (stream, matches) = fields.iter().enumerate().fold( (TokenStream::new(), Vec::new()), |(stream, matches), field| { self.build_inner_pattern( (stream, matches), field, binding_name, |field, ident, binding| { let field_name = field.ident.as_ref().unwrap(); if (self.field_filter)(field) { quote!(#field_name : #binding #ident ,) } else { quote!(#field_name : _ ,) } }, ) }, ); (quote! { { #stream } }, matches) } }; let mut all_tokens = TokenStream::new(); name.to_tokens(&mut all_tokens); all_tokens.extend(stream); (all_tokens, matches) } fn build_inner_pattern<'a>( &self, (mut stream, mut matches): (TokenStream, Vec>), (i, field): (usize, &'a ast::Field), binding_name: &str, f: impl FnOnce(&ast::Field, &syn::Ident, BindingStyle) -> TokenStream, ) -> (TokenStream, Vec>) { let binding_style = self.binding_style; let ident: syn::Ident = syn::Ident::new( &format!("{}_{}", binding_name, i), proc_macro2::Span::call_site(), ); let expr = syn::Expr::Path(syn::ExprPath { attrs: vec![], qself: None, path: syn::Path::from(ident.clone()) }); let expr = if self.is_packed { expr.into_token_stream() } else { quote!((*#expr)) }; f(field, &ident, binding_style).to_tokens(&mut stream); matches.push(BindingInfo { expr, ident, field, }); (stream, matches) } } derivative-2.2.0/src/paths.rs010064400362620024044000000004741400305350200143560ustar0000000000000000//! Contains some standard paths. /// Return the path of the `discriminant` function, that is `::std::mem::discriminant`. pub fn discriminant_path() -> syn::Path { if cfg!(feature = "use_core") { parse_quote!(::core::mem::discriminant) } else { parse_quote!(::std::mem::discriminant) } }derivative-2.2.0/src/utils.rs010064400362620024044000000027001400305350200143710ustar0000000000000000use proc_macro2; use ast; use attr; use bound; use syn; /// Make generic with all the generics in the input, plus a bound `T: ` for each /// generic field type that will be shown. pub fn build_impl_generics( item: &ast::Input, trait_path: &syn::Path, needs_debug_bound: F, field_bound: G, input_bound: H, ) -> syn::Generics where F: Fn(&attr::Field) -> bool, G: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>, H: Fn(&attr::Input) -> Option<&[syn::WherePredicate]>, { let generics = bound::without_defaults(item.generics); let generics = bound::with_where_predicates_from_fields(item, &generics, field_bound); match input_bound(&item.attrs) { Some(predicates) => bound::with_where_predicates(&generics, predicates), None => bound::with_bound(item, &generics, needs_debug_bound, trait_path), } } /// Construct a name for the inner type parameter that can't collide with any /// type parameters of the item. This is achieved by starting with a base and /// then concatenating the names of all other type parameters. pub fn hygienic_type_parameter(item: &ast::Input, base: &str) -> syn::Ident { let mut typaram = String::with_capacity(150); typaram.push_str(base); let typaram = item.generics.type_params().fold(typaram, |mut acc, ty| { acc.push_str(&format!("{}", &ty.ident)); acc }); syn::Ident::new(&typaram, proc_macro2::Span::call_site()) } derivative-2.2.0/tests/clippy-warning-clone-from.rs010064400362620024044000000003171400305350200206100ustar0000000000000000#![deny(clippy::all)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Clone(clone_from = "true"))] pub struct Foo {} fn main() {} derivative-2.2.0/tests/compile-fail/derive-debug-unused.rs010064400362620024044000000004261400305350200220130ustar0000000000000000#![deny(dead_code)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug)] struct Foo { foo: u8, #[derivative(Debug="ignore")] bar: u8, } fn main() { let _ = Foo { foo: 42, bar: 1 }; }derivative-2.2.0/tests/compile-fail/derive-debug-unused.stderr010064400362620024044000000003571400305350200226750ustar0000000000000000error: field is never used: `bar` --> $DIR/derive-debug-unused.rs:14:5 | 14 | bar: u8, | ^^^^^^^ | note: lint level defined here --> $DIR/derive-debug-unused.rs:1:9 | 1 | #![deny(dead_code)] | ^^^^^^^^^ derivative-2.2.0/tests/compile-fail/derive-debug.rs010064400362620024044000000003721400305350200205120ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug)] struct Foo { foo: T, #[derivative(Debug(format_with="std::fmt::Debug::fmt"))] bar: U, } fn main() {}derivative-2.2.0/tests/compile-fail/derive-debug.stderr010064400362620024044000000007441400305350200213740ustar0000000000000000error[E0277]: `U` doesn't implement `std::fmt::Debug` --> $DIR/derive-debug.rs:11:36 | 11 | #[derivative(Debug(format_with="std::fmt::Debug::fmt"))] | ^^^^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` | = help: the trait `std::fmt::Debug` is not implemented for `U` = help: consider adding a `where U: std::fmt::Debug` bound = note: required by `std::fmt::Debug::fmt` derivative-2.2.0/tests/compile-fail/derive-partial-ord.rs010064400362620024044000000002241400305350200216360ustar0000000000000000#[macro_use] extern crate derivative; #[derive(Derivative, PartialEq)] #[derivative(PartialOrd)] enum Option { Some, None, } fn main() {} derivative-2.2.0/tests/compile-fail/derive-partial-ord.stderr010064400362620024044000000003551400305350200225220ustar0000000000000000error: can't use `#[derivative(PartialOrd)]` on an enumeration without `feature_allow_slow_enum`; see the documentation for more details --> $DIR/derive-partial-ord.rs:5:1 | 5 | #[derivative(PartialOrd)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ derivative-2.2.0/tests/compile-fail/invalid-attribute.rs010064400362620024044000000005641400305350200216020ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Clone = not_a_string)] struct Foo1; #[derive(Derivative)] #[derivative(Clone = 1+2)] struct Foo2; #[derive(Derivative)] #[derivative(Default(new = "True"))] struct Foo3; #[derive(Derivative)] #[derivative(Debug(bound))] struct Foo4; fn main() {}derivative-2.2.0/tests/compile-fail/invalid-attribute.stderr010064400362620024044000000011611400305350200224530ustar0000000000000000error: invalid attribute: expected literal --> $DIR/invalid-attribute.rs:8:22 | 8 | #[derivative(Clone = not_a_string)] | ^^^^^^^^^^^^ error: invalid attribute: expected `,` --> $DIR/invalid-attribute.rs:12:23 | 12 | #[derivative(Clone = 1+2)] | ^ error: expected `"true"` or `"false"` for `new`, got `True` --> $DIR/invalid-attribute.rs:16:28 | 16 | #[derivative(Default(new = "True"))] | ^^^^^^ error: expected named value --> $DIR/invalid-attribute.rs:20:20 | 20 | #[derivative(Debug(bound))] | ^^^^^ derivative-2.2.0/tests/compile-fail/unknown-attribute.rs010064400362620024044000000004001400305350200216400ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Clone = "does_not_exist")] struct Foo; #[derive(Derivative)] #[derivative(Clone(does_not_exist = "true"))] struct Bar; fn main() {}derivative-2.2.0/tests/compile-fail/unknown-attribute.stderr010064400362620024044000000005741400305350200225330ustar0000000000000000error: Unknown attribute `does_not_exist` for trait `Clone` --> $DIR/unknown-attribute.rs:8:22 | 8 | #[derivative(Clone = "does_not_exist")] | ^^^^^^^^^^^^^^^^ error: Unknown attribute `does_not_exist` for trait `Clone` --> $DIR/unknown-attribute.rs:12:20 | 12 | #[derivative(Clone(does_not_exist = "true"))] | ^^^^^^^^^^^^^^ derivative-2.2.0/tests/compile-fail/unknown-derive.rs010064400362620024044000000005441400305350200211240ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(DoesNotExist1)] struct Foo; #[derive(Derivative)] #[derivative(DoesNotExist2(with_some="argument"))] struct Bar; #[derive(Derivative)] #[derivative(Debug)] struct Baz { #[derivative(DoesNotExist3)] _baz: (), } fn main() {}derivative-2.2.0/tests/compile-fail/unknown-derive.stderr010064400362620024044000000010261400305350200217770ustar0000000000000000error: deriving `DoesNotExist1` is not supported by derivative --> $DIR/unknown-derive.rs:8:14 | 8 | #[derivative(DoesNotExist1)] | ^^^^^^^^^^^^^ error: deriving `DoesNotExist2` is not supported by derivative --> $DIR/unknown-derive.rs:12:14 | 12 | #[derivative(DoesNotExist2(with_some="argument"))] | ^^^^^^^^^^^^^ error: deriving `DoesNotExist3` is not supported by derivative --> $DIR/unknown-derive.rs:18:18 | 18 | #[derivative(DoesNotExist3)] | ^^^^^^^^^^^^^ derivative-2.2.0/tests/compile-test.rs010064400362620024044000000004131400305350200162100ustar0000000000000000extern crate trybuild; #[test] #[ignore] fn compile_test() { let t = trybuild::TestCases::new(); let pattern = std::env::var("DERIVATIVE_TEST_FILTER").unwrap_or_else(|_| String::from("*.rs")); t.compile_fail(format!("tests/compile-fail/{}", pattern)); } derivative-2.2.0/tests/derive-clone-generics.rs010064400362620024044000000011731400305350200177600ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; use std::marker::PhantomData; struct NoClone; #[derive(Derivative)] #[derivative(Clone, PartialEq)] struct PhantomField { foo: PhantomData, } #[derive(Derivative)] #[derivative(Clone, PartialEq)] struct PhantomTuple { foo: PhantomData<(T,)>, } #[test] fn main() { let phantom_field = PhantomField:: { foo: Default::default() }; let phantom_tuple = PhantomTuple:: { foo: Default::default() }; assert!(phantom_field == phantom_field.clone()); assert!(phantom_tuple == phantom_tuple.clone()); } derivative-2.2.0/tests/derive-clone.rs010075500362620024044000000031161400305350200161650ustar0000000000000000#![allow(clippy::blacklisted_name, clippy::redundant_clone, clippy::trivially_copy_pass_by_ref)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Debug, Derivative, PartialEq)] #[derivative(Clone)] struct Foo { foo: u8, #[derivative(Clone(clone_with="seventh"))] bar: u8, } fn seventh(a: &u8) -> u8 { a/7 } #[derive(Debug, PartialEq)] struct EvilCloneFrom(u8); impl Clone for EvilCloneFrom { fn clone(&self) -> Self { EvilCloneFrom(self.0) } fn clone_from(&mut self, _: &Self) { self.0 = 42; } } #[derive(Derivative)] #[derivative(Clone(clone_from="true"))] struct StructWithCloneFrom(EvilCloneFrom); #[derive(Debug, Derivative, PartialEq)] #[derivative(Clone(clone_from="true"))] enum EnumWithCloneFrom { Evil(EvilCloneFrom), Good(u32), None } #[test] fn main() { let foo = Foo { foo: 31, bar: 42 }; assert_eq!(Foo { foo: 31, bar: 6 }, foo.clone()); let mut foo = StructWithCloneFrom(EvilCloneFrom(27)); foo.clone_from(&StructWithCloneFrom(EvilCloneFrom(0))); assert_eq!((foo.0).0, 42); let mut foo = EnumWithCloneFrom::Evil(EvilCloneFrom(27)); foo.clone_from(&EnumWithCloneFrom::Evil(EvilCloneFrom(0))); assert_eq!(foo, EnumWithCloneFrom::Evil(EvilCloneFrom(42))); let mut foo = EnumWithCloneFrom::Evil(EvilCloneFrom(27)); foo.clone_from(&EnumWithCloneFrom::None); assert_eq!(foo, EnumWithCloneFrom::None); let mut foo = EnumWithCloneFrom::Good(27); foo.clone_from(&EnumWithCloneFrom::None); assert_eq!(foo, EnumWithCloneFrom::None); } derivative-2.2.0/tests/derive-debug-bounds.rs010064400362620024044000000037621400305350200174470ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; use std::fmt::{Formatter, Result as FmtResult}; #[derive(Derivative)] #[derivative(Debug)] struct Foo { foo: T, #[derivative(Debug(format_with="MyDebug::my_fmt", bound="U: MyDebug"))] bar: U, } #[derive(Derivative)] #[derivative(Debug(bound="T: std::fmt::Debug, U: MyDebug"))] struct Foo2 { foo: T, #[derivative(Debug(format_with="MyDebug::my_fmt"))] bar: U, } #[derive(Derivative)] #[derivative(Debug)] struct Bar ( T, #[derivative(Debug(format_with="MyDebug::my_fmt", bound="U: MyDebug"))] U, ); #[derive(Derivative)] #[derivative(Debug(bound="T: std::fmt::Debug, U: MyDebug"))] struct Bar2 ( T, #[derivative(Debug(format_with="MyDebug::my_fmt"))] U, ); struct NoDebug; struct GenericNeedsNoDebug(T); impl std::fmt::Debug for GenericNeedsNoDebug { fn fmt(&self, f: &mut std::fmt::Formatter) -> FmtResult { f.write_str("GenericNeedsNoDebug") } } #[derive(Derivative)] #[derivative(Debug)] struct TestUnneededBound( // Test that we don't add T: Debug #[derivative(Debug(bound=""))] GenericNeedsNoDebug, ); trait MyDebug { fn my_fmt(&self, f: &mut Formatter) -> FmtResult { f.write_str("MyDebug") } } impl MyDebug for i32 { } impl<'a, T> MyDebug for &'a T { } trait ToDebug { fn to_show(&self) -> String; } impl ToDebug for T { fn to_show(&self) -> String { format!("{:?}", self) } } #[test] fn main() { assert_eq!(Foo { foo: 42, bar: 0 }.to_show(), "Foo { foo: 42, bar: MyDebug }".to_string()); assert_eq!(Foo2 { foo: 42, bar: 0 }.to_show(), "Foo2 { foo: 42, bar: MyDebug }".to_string()); assert_eq!(Bar(42, 0).to_show(), "Bar(42, MyDebug)".to_string()); assert_eq!(Bar2(42, 0).to_show(), "Bar2(42, MyDebug)".to_string()); assert_eq!(TestUnneededBound(GenericNeedsNoDebug(NoDebug)).to_show(), "TestUnneededBound(GenericNeedsNoDebug)".to_string()); } derivative-2.2.0/tests/derive-debug-generics.rs010064400362620024044000000042241400305350200177460ustar0000000000000000#![allow(dead_code)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; use std::marker::PhantomData; #[derive(Derivative)] #[derivative(Debug)] struct Foo { foo: T, #[derivative(Debug="ignore")] bar: U, } #[derive(Derivative)] #[derivative(Debug)] struct Bar ( T, #[derivative(Debug="ignore")] U, ); #[derive(Derivative)] #[derivative(Debug)] enum C { V1(T), V2(#[derivative(Debug="ignore")] U), V3(String), } #[derive(Derivative)] #[derivative(Debug)] enum D { V1 { #[derivative(Debug="ignore")] a: U } } #[derive(Derivative)] #[derivative(Debug)] struct F(#[derivative(Debug="ignore")] U); #[derive(Derivative)] #[derivative(Debug)] struct G(isize, #[derivative(Debug="ignore")] U); #[derive(Derivative)] #[derivative(Debug)] struct J(#[derivative(Debug="ignore")] U); struct NoDebug; trait ToDebug { fn to_show(&self) -> String; } impl ToDebug for T { fn to_show(&self) -> String { format!("{:?}", self) } } #[derive(Derivative)] #[derivative(Debug)] struct PhantomField { foo: PhantomData, } #[derive(Derivative)] #[derivative(Debug)] struct PhantomTuple { foo: PhantomData<(T,)>, } #[test] fn main() { assert_eq!(Foo { foo: 42, bar: NoDebug }.to_show(), "Foo { foo: 42 }".to_string()); assert_eq!(Bar(42, NoDebug).to_show(), "Bar(42)".to_string()); assert_eq!(C::V1::(12).to_show(), "V1(12)".to_string()); assert_eq!(C::V2::(NoDebug).to_show(), "V2".to_string()); assert_eq!(C::V3::("foo".to_string()).to_show(), "V3(\"foo\")".to_string()); assert_eq!(D::V1 { a: NoDebug }.to_show(), "V1".to_string()); assert_eq!(F(NoDebug).to_show(), "F".to_string()); assert_eq!(G(42, NoDebug).to_show(), "G(42)".to_string()); assert_eq!(J(NoDebug).to_show(), "J".to_string()); assert_eq!(&format!("{:?}", PhantomField:: { foo: Default::default() }), "PhantomField { foo: PhantomData }"); assert_eq!(&format!("{:?}", PhantomTuple:: { foo: Default::default() }), "PhantomTuple { foo: PhantomData }"); } derivative-2.2.0/tests/derive-debug-packed.rs010064400362620024044000000030471400305350200174000ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug)] #[repr(C, packed)] struct Foo { foo: u8, #[derivative(Debug="ignore")] bar: u8, } #[derive(Derivative)] #[derivative(Debug)] #[repr(C, packed)] struct Bar ( u8, #[derivative(Debug="ignore")] u8, ); #[derive(Derivative)] #[derivative(Debug)] #[repr(C, packed)] struct F(#[derivative(Debug="ignore")] isize); #[derive(Derivative)] #[derivative(Debug)] #[repr(C, packed)] struct G(isize, #[derivative(Debug="ignore")] isize); #[derive(Derivative)] #[derivative(Debug)] #[repr(C, packed)] struct J(#[derivative(Debug="ignore")] NoDebug); #[derive(Derivative)] #[derivative(Debug)] #[repr(C, packed)] struct K(isize, #[derivative(Debug="ignore")] NoDebug); #[derive(Derivative)] #[derivative(Debug)] #[repr(C, packed)] struct L { #[derivative(Debug="ignore")] foo: NoDebug } struct NoDebug; trait ToDebug { fn to_show(&self) -> String; } impl ToDebug for T { fn to_show(&self) -> String { format!("{:?}", self) } } #[test] fn main() { assert_eq!(Foo { foo: 42, bar: 1 }.to_show(), "Foo { foo: 42 }".to_string()); assert_eq!(Bar(42, 1).to_show(), "Bar(42)".to_string()); assert_eq!(F(42).to_show(), "F".to_string()); assert_eq!(G(42, 0).to_show(), "G(42)".to_string()); assert_eq!(J(NoDebug).to_show(), "J".to_string()); assert_eq!(K(42, NoDebug).to_show(), "K(42)".to_string()); assert_eq!(L{ foo: NoDebug }.to_show(), "L".to_string()); } derivative-2.2.0/tests/derive-debug-transparent.rs010064400362620024044000000014061400305350200205070ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug="transparent")] struct A(isize); #[derive(Derivative)] #[derivative(Debug="transparent")] struct B([isize; 1]); #[derive(Derivative)] #[derivative(Debug)] enum C { Foo(u8), #[derivative(Debug="transparent")] Bar(u8), } trait ToDebug { fn to_show(&self) -> String; } impl ToDebug for T { fn to_show(&self) -> String { format!("{:?}", self) } } #[test] fn main() { assert_eq!(A(42).to_show(), "42".to_string()); assert_eq!(B([42]).to_show(), "[42]".to_string()); assert_eq!(C::Foo(42).to_show(), "Foo(42)".to_string()); assert_eq!(C::Bar(42).to_show(), "42".to_string()); } derivative-2.2.0/tests/derive-debug.rs010064400362620024044000000031471400305350200161540ustar0000000000000000#![allow(dead_code)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug)] struct Foo { foo: u8, #[derivative(Debug="ignore")] bar: u8, } #[derive(Derivative)] #[derivative(Debug)] struct Bar ( u8, #[derivative(Debug="ignore")] u8, ); #[derive(Derivative)] #[derivative(Debug)] enum C { V1(isize), V2(#[derivative(Debug="ignore")] i32), V3(String), } #[derive(Derivative)] #[derivative(Debug)] enum D { V1 { #[derivative(Debug="ignore")] a: isize } } #[derive(Derivative)] #[derivative(Debug)] struct F(#[derivative(Debug="ignore")] isize); #[derive(Derivative)] #[derivative(Debug)] struct G(isize, #[derivative(Debug="ignore")] isize); #[derive(Derivative)] #[derivative(Debug)] struct J(#[derivative(Debug="ignore")] NoDebug); struct NoDebug; trait ToDebug { fn to_show(&self) -> String; } impl ToDebug for T { fn to_show(&self) -> String { format!("{:?}", self) } } #[test] fn main() { assert_eq!(Foo { foo: 42, bar: 1 }.to_show(), "Foo { foo: 42 }".to_string()); assert_eq!(Bar(42, 1).to_show(), "Bar(42)".to_string()); assert_eq!(C::V1(12).to_show(), "V1(12)".to_string()); assert_eq!(C::V2(12).to_show(), "V2".to_string()); assert_eq!(C::V3("foo".to_string()).to_show(), "V3(\"foo\")".to_string()); assert_eq!(D::V1 { a: 42 }.to_show(), "V1".to_string()); assert_eq!(F(42).to_show(), "F".to_string()); assert_eq!(G(42, 0).to_show(), "G(42)".to_string()); assert_eq!(J(NoDebug).to_show(), "J".to_string()); } derivative-2.2.0/tests/derive-default-bounds.rs010075500362620024044000000020151400305350200177760ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Debug, Derivative, PartialEq)] #[derivative(Default="new")] struct Foo { foo: T, #[derivative(Default(value="min()", bound="U: std::ops::Not, U: Default"))] bar: U, } #[derive(Debug, Derivative, PartialEq)] #[derivative(Default(bound="T: Default, U: std::ops::Not, U: Default", new="true"))] struct Bar { foo: T, #[derivative(Default(value="min()"))] bar: U, } fn min>() -> T { !T::default() } #[derive(Debug, Derivative, PartialEq)] #[derivative(Default(bound=""))] struct WithOption { foo: Option, } struct NonDefault; #[test] fn main() { assert_eq!(Foo::default(), Foo { foo: 0u8, bar: 0xffu8 }); assert_eq!(Bar::default(), Bar { foo: 0u8, bar: 0xffu8 }); assert_eq!(Foo::new(), Foo { foo: 0u8, bar: 0xffu8 }); assert_eq!(Bar::new(), Bar { foo: 0u8, bar: 0xffu8 }); WithOption::::default(); } derivative-2.2.0/tests/derive-default.rs010064400362620024044000000033051400305350200165060ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Debug, Derivative, PartialEq)] #[derivative(Default="new")] struct Foo { foo: u8, #[derivative(Default(value="42"))] bar: u8, } #[derive(Debug, Derivative, PartialEq)] #[derivative(Default(new="true"))] struct Bar ( u8, #[derivative(Default(value="42"))] u8, ); #[derive(Debug, PartialEq)] struct B1(u8, u8); #[derive(Debug, PartialEq)] struct B2{a:u8, b:u8} #[derive(Debug, Derivative, PartialEq)] #[derivative(Default(new="true"))] struct Baz ( #[derivative(Default(value="[1,2]"))] [u8;2], #[derivative(Default(value="[3;2]"))] [u8;2], #[derivative(Default(value="(4,5)"))] (u8, u8), #[derivative(Default(value="B1(6,7)"))] B1, #[derivative(Default(value="B2{a:8,b:9}"))] B2, ); #[derive(Debug, Derivative, PartialEq)] #[derivative(Default)] enum Enum1 { #[allow(dead_code)] A, #[derivative(Default)] B, } #[derive(Debug, Derivative, PartialEq)] #[derivative(Default)] enum Enum2 { #[derivative(Default)] A, #[allow(dead_code)] B, } #[derive(Debug, Derivative, PartialEq)] #[derivative(Default)] struct A(#[derivative(Default(value="NoDefault"))] NoDefault); #[derive(Debug, PartialEq)] struct NoDefault; #[test] fn main() { assert_eq!(Foo::default(), Foo { foo: 0, bar: 42 }); assert_eq!(Foo::new(), Foo { foo: 0, bar: 42 }); assert_eq!(Bar::default(), Bar(0, 42)); assert_eq!(Bar::new(), Bar(0, 42)); assert_eq!(Baz::new(), Baz([1,2], [3,3], (4,5), B1(6,7), B2{a:8,b:9})); assert_eq!(A::default(), A(NoDefault)); assert_eq!(Enum1::default(), Enum1::B); assert_eq!(Enum2::default(), Enum2::A); } derivative-2.2.0/tests/derive-eq-packed.rs010064400362620024044000000024151400305350200167150ustar0000000000000000#![allow(clippy::eq_op)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative, PartialEq)] #[derivative(Eq)] #[repr(C, packed)] struct Foo { foo: u8 } #[derive(Derivative)] #[derivative(Eq)] #[repr(C, packed)] struct WithPtr { #[derivative(Eq(bound=""))] foo: *const T } impl PartialEq for WithPtr { fn eq(&self, other: &Self) -> bool { self.foo == other.foo } } #[derive(Derivative)] #[derivative(PartialEq, Eq)] #[repr(C, packed)] struct Generic(T); trait SomeTrait {} #[derive(Clone, Copy, PartialEq, Eq)] struct SomeType { #[allow(dead_code)] foo: u8 } impl SomeTrait for SomeType {} fn assert_eq(_: T) {} #[test] fn main() { assert!(Foo { foo: 7 } == Foo { foo: 7 }); assert!(Foo { foo: 7 } != Foo { foo: 42 }); assert_eq(Foo { foo: 7 }); let ptr1: *const dyn SomeTrait = &SomeType { foo: 0 }; let ptr2: *const dyn SomeTrait = &SomeType { foo: 1 }; assert!(WithPtr { foo: ptr1 } == WithPtr { foo: ptr1 }); assert!(WithPtr { foo: ptr1 } != WithPtr { foo: ptr2 }); assert_eq(WithPtr { foo: ptr1 }); assert!(Generic(SomeType { foo: 0 }) == Generic(SomeType { foo: 0 })); assert_eq(Generic(SomeType { foo: 0 })); } derivative-2.2.0/tests/derive-eq.rs010064400362620024044000000017531400305350200154740ustar0000000000000000#![allow(clippy::eq_op)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative, PartialEq)] #[derivative(Eq)] struct Foo { foo: u8 } #[derive(Derivative)] #[derivative(Eq)] struct WithPtr { #[derivative(Eq(bound=""))] foo: *const T } impl PartialEq for WithPtr { fn eq(&self, other: &Self) -> bool { self.foo == other.foo } } trait SomeTrait {} struct SomeType { #[allow(dead_code)] foo: u8 } impl SomeTrait for SomeType {} fn assert_eq(_: T) {} #[test] fn main() { assert!(Foo { foo: 7 } == Foo { foo: 7 }); assert!(Foo { foo: 7 } != Foo { foo: 42 }); assert_eq(Foo { foo: 7 }); let ptr1: *const dyn SomeTrait = &SomeType { foo: 0 }; let ptr2: *const dyn SomeTrait = &SomeType { foo: 1 }; assert!(WithPtr { foo: ptr1 } == WithPtr { foo: ptr1 }); assert!(WithPtr { foo: ptr1 } != WithPtr { foo: ptr2 }); assert_eq(WithPtr { foo: ptr1 }); } derivative-2.2.0/tests/derive-hash.rs010075500362620024044000000060441400305350200160130ustar0000000000000000//! This tests that we compute the same hash as `derive(Hash)`. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; macro_rules! define { ($kw:tt $($rest:tt)*) => { #[derive(Derivative)] #[derivative(Hash)] $kw Ours $($rest)* #[derive(Hash)] $kw Theirs $($rest)* } } struct FakeHasher<'a>(&'a mut Vec); impl<'a> ::std::hash::Hasher for FakeHasher<'a> { fn finish(&self) -> u64 { unimplemented!() } fn write(&mut self, bytes: &[u8]) { self.0.extend(bytes); } } fn fake_hash(e: E) -> Vec { let mut v = Vec::new(); e.hash(&mut FakeHasher(&mut v)); v } #[test] fn main() { { define! { struct; } assert_eq!(fake_hash(Ours), fake_hash(Theirs)); } { define! { struct { foo: u8 } } assert_eq!(fake_hash(Ours { foo: 0 }), fake_hash(Theirs { foo: 0 })); assert_eq!(fake_hash(Ours { foo: 42 }), fake_hash(Theirs { foo: 42 })); } { define! { struct<'a> { foo: u8, bar: &'a str, } } assert_eq!(fake_hash(Ours { foo: 0, bar: "bar" }), fake_hash(Theirs { foo: 0, bar: "bar" })); assert_eq!(fake_hash(Ours { foo: 42, bar: "bar" }), fake_hash(Theirs { foo: 42, bar: "bar" })); } { define! { struct<'a> (u8, &'a str); } assert_eq!(fake_hash(Ours ( 0, "bar" )), fake_hash(Theirs ( 0, "bar" ))); assert_eq!(fake_hash(Ours ( 42, "bar" )), fake_hash(Theirs ( 42, "bar" ))); } { define! { enum { A, B, C } } assert_eq!(fake_hash(Ours::A), fake_hash(Theirs::A)); assert_eq!(fake_hash(Ours::B), fake_hash(Theirs::B)); assert_eq!(fake_hash(Ours::C), fake_hash(Theirs::C)); } { define! { enum { A, B = 42, C } } assert_eq!(fake_hash(Ours::A), fake_hash(Theirs::A)); assert_eq!(fake_hash(Ours::B), fake_hash(Theirs::B)); assert_eq!(fake_hash(Ours::C), fake_hash(Theirs::C)); } { define! { enum { A, B = 42, C=1 } } assert_eq!(fake_hash(Ours::A), fake_hash(Theirs::A)); assert_eq!(fake_hash(Ours::B), fake_hash(Theirs::B)); assert_eq!(fake_hash(Ours::C), fake_hash(Theirs::C)); } { #[derive(Derivative)] #[derivative(Hash)] struct Ours<'a> { foo: u8, #[derivative(Hash="ignore")] bar: &'a str, baz: i64, } #[derive(Hash)] struct Theirs { foo: u8, baz: i64, } assert_eq!(fake_hash(Ours { foo: 0, bar: "bar", baz: 312 }), fake_hash(Theirs { foo: 0, baz: 312 })); assert_eq!(fake_hash(Ours { foo: 42, bar: "bar", baz: 312 }), fake_hash(Theirs { foo: 42, baz: 312 })); } } derivative-2.2.0/tests/derive-ord-packed.rs010064400362620024044000000163661400305350200171060ustar0000000000000000#![allow(renamed_and_removed_lints)] // clippy::cyclomatic_complexity → clippy::cognitive_complexity #![allow(clippy::cyclomatic_complexity)] #![allow(clippy::cognitive_complexity)] #![allow(clippy::trivially_copy_pass_by_ref)] #![allow(clippy::unknown_clippy_lints)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(PartialEq, Eq, Derivative)] #[derivative(PartialOrd, Ord)] #[repr(C, packed)] struct Foo { foo: u8, } #[derive(Derivative)] #[derivative(PartialEq, PartialOrd, Ord, Eq)] #[repr(C, packed)] struct WithPtr { #[derivative(PartialEq(bound = ""))] #[derivative(PartialOrd(bound = ""))] #[derivative(Ord(bound = ""))] #[derivative(Eq(bound = ""))] foo: *const T, } #[derive(PartialEq, Eq, Derivative)] #[derivative(PartialOrd, Ord)] #[repr(C, packed)] struct Empty; #[derive(PartialEq, Eq, Derivative)] #[derivative(PartialOrd, Ord)] #[repr(C, packed)] struct AllIgnored { #[derivative(PartialOrd = "ignore")] #[derivative(Ord = "ignore")] foo: u8, } #[derive(PartialEq, Eq, Derivative)] #[derivative(PartialOrd, Ord)] #[repr(C, packed)] struct OneIgnored { #[derivative(PartialOrd = "ignore")] #[derivative(Ord = "ignore")] foo: u8, bar: u8, } #[derive(PartialEq, Eq, Derivative)] #[derivative(PartialOrd, Ord)] #[repr(C, packed)] struct Tenth( #[derivative( PartialOrd(compare_with = "partial_cmp_tenth"), Ord(compare_with = "cmp_tenth") )] u8, ); fn partial_cmp_tenth(lhs: &u8, rhs: &u8) -> std::option::Option { if *lhs == 0 { None } else { Some((lhs / 10).cmp(&(rhs / 10))) } } fn cmp_tenth(lhs: &u8, rhs: &u8) -> std::cmp::Ordering { (lhs / 10).cmp(&(rhs / 10)) } #[derive(Derivative)] #[derivative(PartialOrd, Ord, PartialEq, Eq)] #[repr(C, packed)] struct Generic( #[derivative( PartialEq = "ignore", PartialOrd(compare_with = "dummy_partial_cmp", bound = ""), Ord(compare_with = "dummy_cmp", bound = "") )] T, ); fn dummy_partial_cmp(_: &T, _: &T) -> std::option::Option { Some(std::cmp::Ordering::Less) } fn dummy_cmp(_: &T, _: &T) -> std::cmp::Ordering { std::cmp::Ordering::Less } struct NonPartialOrd; #[derive(Derivative)] #[derivative(PartialEq, PartialOrd, Ord, Eq)] #[repr(C, packed)] struct GenericIgnore { f: u32, #[derivative(PartialEq = "ignore")] #[derivative(PartialOrd = "ignore")] #[derivative(Ord = "ignore")] t: T, } trait SomeTrait {} #[derive(Clone, Copy)] struct SomeType { #[allow(dead_code)] foo: u8, } impl SomeTrait for SomeType {} #[test] fn main() { use std::cmp::Ordering; assert_eq!( Foo { foo: 7 }.partial_cmp(&Foo { foo: 42 }), Some(Ordering::Less) ); assert_eq!( Foo { foo: 42 }.partial_cmp(&Foo { foo: 42 }), Some(Ordering::Equal) ); assert_eq!( Foo { foo: 42 }.partial_cmp(&Foo { foo: 7 }), Some(Ordering::Greater) ); assert_eq!(Foo { foo: 7 }.cmp(&Foo { foo: 42 }), Ordering::Less); assert_eq!(Foo { foo: 42 }.cmp(&Foo { foo: 42 }), Ordering::Equal); assert_eq!(Foo { foo: 42 }.cmp(&Foo { foo: 7 }), Ordering::Greater); let pointers: [*const dyn SomeTrait; 2] = [&SomeType { foo: 1 }, &SomeType { foo: 0 }]; let ptr1: *const dyn SomeTrait = pointers[0]; let ptr2: *const dyn SomeTrait = pointers[1]; let (ptr1, ptr2) = (std::cmp::min(ptr1, ptr2), std::cmp::max(ptr1, ptr2)); assert_eq!( WithPtr { foo: ptr1 }.partial_cmp(&WithPtr { foo: ptr1 }), Some(Ordering::Equal) ); assert_eq!( WithPtr { foo: ptr1 }.cmp(&WithPtr { foo: ptr1 }), Ordering::Equal ); assert_eq!( WithPtr { foo: ptr1 }.partial_cmp(&WithPtr { foo: ptr2 }), Some(Ordering::Less) ); assert_eq!( WithPtr { foo: ptr1 }.cmp(&WithPtr { foo: ptr2 }), Ordering::Less ); assert_eq!(Empty.partial_cmp(&Empty), Some(Ordering::Equal)); assert_eq!( AllIgnored { foo: 0 }.partial_cmp(&AllIgnored { foo: 42 }), Some(Ordering::Equal) ); assert_eq!( OneIgnored { foo: 0, bar: 6 }.partial_cmp(&OneIgnored { foo: 42, bar: 7 }), Some(Ordering::Less) ); assert_eq!( OneIgnored { foo: 0, bar: 6 }.partial_cmp(&OneIgnored { foo: 42, bar: 6 }), Some(Ordering::Equal) ); assert_eq!( OneIgnored { foo: 0, bar: 7 }.partial_cmp(&OneIgnored { foo: 42, bar: 6 }), Some(Ordering::Greater) ); assert_eq!(Empty.cmp(&Empty), Ordering::Equal); assert_eq!( AllIgnored { foo: 0 }.cmp(&AllIgnored { foo: 42 }), Ordering::Equal ); assert_eq!( OneIgnored { foo: 0, bar: 6 }.cmp(&OneIgnored { foo: 42, bar: 7 }), Ordering::Less ); assert_eq!( OneIgnored { foo: 0, bar: 6 }.cmp(&OneIgnored { foo: 42, bar: 6 }), Ordering::Equal ); assert_eq!( OneIgnored { foo: 0, bar: 7 }.cmp(&OneIgnored { foo: 42, bar: 6 }), Ordering::Greater ); assert_eq!( Option::None::.partial_cmp(&Option::Some(7)), Some(Ordering::Less) ); assert_eq!( Option::Some(6).partial_cmp(&Option::Some(7)), Some(Ordering::Less) ); assert_eq!( Option::Some(42).partial_cmp(&Option::Some(42)), Some(Ordering::Equal) ); assert_eq!( Option::None::.partial_cmp(&Option::None::), Some(Ordering::Equal) ); assert_eq!( Option::Some(7).partial_cmp(&Option::Some(6)), Some(Ordering::Greater) ); assert_eq!( Option::Some(7).partial_cmp(&Option::None::), Some(Ordering::Greater) ); assert_eq!(Option::None::.cmp(&Option::Some(7)), Ordering::Less); assert_eq!(Option::Some(6).cmp(&Option::Some(7)), Ordering::Less); assert_eq!(Option::Some(42).cmp(&Option::Some(42)), Ordering::Equal); assert_eq!(Option::None::.cmp(&Option::None::), Ordering::Equal); assert_eq!(Option::Some(7).cmp(&Option::Some(6)), Ordering::Greater); assert_eq!(Option::Some(7).cmp(&Option::None::), Ordering::Greater); assert_eq!(Tenth(0).partial_cmp(&Tenth(67)), None); assert_eq!(Tenth(42).partial_cmp(&Tenth(67)), Some(Ordering::Less)); assert_eq!(Tenth(60).partial_cmp(&Tenth(67)), Some(Ordering::Equal)); assert_eq!(Tenth(100).partial_cmp(&Tenth(67)), Some(Ordering::Greater)); assert_eq!(Tenth(42).cmp(&Tenth(67)), Ordering::Less); assert_eq!(Tenth(60).cmp(&Tenth(67)), Ordering::Equal); assert_eq!(Tenth(100).cmp(&Tenth(67)), Ordering::Greater); assert_eq!( Generic(SomeType { foo: 0 }).partial_cmp(&Generic(SomeType { foo: 0 })), Some(Ordering::Less) ); assert_eq!( Generic(SomeType { foo: 0 }).cmp(&Generic(SomeType { foo: 0 })), Ordering::Less ); assert_eq!( GenericIgnore { f: 123, t: NonPartialOrd } .cmp(&GenericIgnore { f: 123, t: NonPartialOrd }), Ordering::Equal ); assert_eq!( GenericIgnore { f: 123, t: NonPartialOrd } .partial_cmp(&GenericIgnore { f: 123, t: NonPartialOrd }), Some(Ordering::Equal) ); } derivative-2.2.0/tests/derive-ord.rs010064400362620024044000000166131400305350200156540ustar0000000000000000#![allow(renamed_and_removed_lints)] // clippy::cyclomatic_complexity → clippy::cognitive_complexity #![allow(clippy::cyclomatic_complexity)] #![allow(clippy::cognitive_complexity)] #![allow(clippy::trivially_copy_pass_by_ref)] #![allow(clippy::unknown_clippy_lints)] #[cfg(feature = "use_core")] extern crate core; use std::marker::PhantomData; #[macro_use] extern crate derivative; #[derive(PartialEq, Eq, Derivative)] #[derivative(PartialOrd, Ord)] struct Foo { foo: u8, } #[derive(PartialEq, Eq, Derivative)] #[derivative( PartialOrd = "feature_allow_slow_enum", Ord = "feature_allow_slow_enum" )] enum Option { None, Some(T), } #[derive(Derivative)] #[derivative(PartialEq, PartialOrd, Ord, Eq)] struct WithPtr { #[derivative(PartialEq(bound = ""))] #[derivative(PartialOrd(bound = ""))] #[derivative(Ord(bound = ""))] #[derivative(Eq(bound = ""))] foo: *const T, } #[derive(PartialEq, Eq, Derivative)] #[derivative(PartialOrd, Ord)] struct Empty; #[derive(PartialEq, Eq, Derivative)] #[derivative(PartialOrd, Ord)] struct AllIgnored { #[derivative(PartialOrd = "ignore")] #[derivative(Ord = "ignore")] foo: u8, } #[derive(PartialEq, Eq, Derivative)] #[derivative(PartialOrd, Ord)] struct OneIgnored { #[derivative(PartialOrd = "ignore")] #[derivative(Ord = "ignore")] foo: u8, bar: u8, } #[derive(PartialEq, Eq, Derivative)] #[derivative(PartialOrd, Ord)] struct Tenth( #[derivative( PartialOrd(compare_with = "partial_cmp_tenth"), Ord(compare_with = "cmp_tenth") )] u8, ); fn partial_cmp_tenth(lhs: &u8, rhs: &u8) -> std::option::Option { if *lhs == 0 { None } else { Some((lhs / 10).cmp(&(rhs / 10))) } } fn cmp_tenth(lhs: &u8, rhs: &u8) -> std::cmp::Ordering { (lhs / 10).cmp(&(rhs / 10)) } #[derive(Derivative)] #[derivative(PartialOrd, Ord, PartialEq, Eq)] struct Generic( #[derivative( PartialEq = "ignore", PartialOrd(compare_with = "dummy_partial_cmp", bound = ""), Ord(compare_with = "dummy_cmp", bound = "") )] T, ); fn dummy_partial_cmp(_: &T, _: &T) -> std::option::Option { Some(std::cmp::Ordering::Less) } fn dummy_cmp(_: &T, _: &T) -> std::cmp::Ordering { std::cmp::Ordering::Less } struct NonPartialOrd; #[derive(Derivative)] #[derivative(PartialEq, PartialOrd, Ord, Eq)] struct GenericIgnore { f: u32, #[derivative(PartialEq = "ignore")] #[derivative(PartialOrd = "ignore")] #[derivative(Ord = "ignore")] t: PhantomData, } trait SomeTrait {} struct SomeType { #[allow(dead_code)] foo: u8, } impl SomeTrait for SomeType {} #[test] fn main() { use std::cmp::Ordering; assert_eq!( Foo { foo: 7 }.partial_cmp(&Foo { foo: 42 }), Some(Ordering::Less) ); assert_eq!( Foo { foo: 42 }.partial_cmp(&Foo { foo: 42 }), Some(Ordering::Equal) ); assert_eq!( Foo { foo: 42 }.partial_cmp(&Foo { foo: 7 }), Some(Ordering::Greater) ); assert_eq!(Foo { foo: 7 }.cmp(&Foo { foo: 42 }), Ordering::Less); assert_eq!(Foo { foo: 42 }.cmp(&Foo { foo: 42 }), Ordering::Equal); assert_eq!(Foo { foo: 42 }.cmp(&Foo { foo: 7 }), Ordering::Greater); let pointers: [*const dyn SomeTrait; 2] = [&SomeType { foo: 1 }, &SomeType { foo: 0 }]; let ptr1: *const dyn SomeTrait = pointers[0]; let ptr2: *const dyn SomeTrait = pointers[1]; let (ptr1, ptr2) = (std::cmp::min(ptr1, ptr2), std::cmp::max(ptr1, ptr2)); assert_eq!( WithPtr { foo: ptr1 }.partial_cmp(&WithPtr { foo: ptr1 }), Some(Ordering::Equal) ); assert_eq!( WithPtr { foo: ptr1 }.cmp(&WithPtr { foo: ptr1 }), Ordering::Equal ); assert_eq!( WithPtr { foo: ptr1 }.partial_cmp(&WithPtr { foo: ptr2 }), Some(Ordering::Less) ); assert_eq!( WithPtr { foo: ptr1 }.cmp(&WithPtr { foo: ptr2 }), Ordering::Less ); assert_eq!(Empty.partial_cmp(&Empty), Some(Ordering::Equal)); assert_eq!( AllIgnored { foo: 0 }.partial_cmp(&AllIgnored { foo: 42 }), Some(Ordering::Equal) ); assert_eq!( OneIgnored { foo: 0, bar: 6 }.partial_cmp(&OneIgnored { foo: 42, bar: 7 }), Some(Ordering::Less) ); assert_eq!( OneIgnored { foo: 0, bar: 6 }.partial_cmp(&OneIgnored { foo: 42, bar: 6 }), Some(Ordering::Equal) ); assert_eq!( OneIgnored { foo: 0, bar: 7 }.partial_cmp(&OneIgnored { foo: 42, bar: 6 }), Some(Ordering::Greater) ); assert_eq!(Empty.cmp(&Empty), Ordering::Equal); assert_eq!( AllIgnored { foo: 0 }.cmp(&AllIgnored { foo: 42 }), Ordering::Equal ); assert_eq!( OneIgnored { foo: 0, bar: 6 }.cmp(&OneIgnored { foo: 42, bar: 7 }), Ordering::Less ); assert_eq!( OneIgnored { foo: 0, bar: 6 }.cmp(&OneIgnored { foo: 42, bar: 6 }), Ordering::Equal ); assert_eq!( OneIgnored { foo: 0, bar: 7 }.cmp(&OneIgnored { foo: 42, bar: 6 }), Ordering::Greater ); assert_eq!( Option::None::.partial_cmp(&Option::Some(7)), Some(Ordering::Less) ); assert_eq!( Option::Some(6).partial_cmp(&Option::Some(7)), Some(Ordering::Less) ); assert_eq!( Option::Some(42).partial_cmp(&Option::Some(42)), Some(Ordering::Equal) ); assert_eq!( Option::None::.partial_cmp(&Option::None::), Some(Ordering::Equal) ); assert_eq!( Option::Some(7).partial_cmp(&Option::Some(6)), Some(Ordering::Greater) ); assert_eq!( Option::Some(7).partial_cmp(&Option::None::), Some(Ordering::Greater) ); assert_eq!(Option::None::.cmp(&Option::Some(7)), Ordering::Less); assert_eq!(Option::Some(6).cmp(&Option::Some(7)), Ordering::Less); assert_eq!(Option::Some(42).cmp(&Option::Some(42)), Ordering::Equal); assert_eq!(Option::None::.cmp(&Option::None::), Ordering::Equal); assert_eq!(Option::Some(7).cmp(&Option::Some(6)), Ordering::Greater); assert_eq!(Option::Some(7).cmp(&Option::None::), Ordering::Greater); assert_eq!(Tenth(0).partial_cmp(&Tenth(67)), None); assert_eq!(Tenth(42).partial_cmp(&Tenth(67)), Some(Ordering::Less)); assert_eq!(Tenth(60).partial_cmp(&Tenth(67)), Some(Ordering::Equal)); assert_eq!(Tenth(100).partial_cmp(&Tenth(67)), Some(Ordering::Greater)); assert_eq!(Tenth(42).cmp(&Tenth(67)), Ordering::Less); assert_eq!(Tenth(60).cmp(&Tenth(67)), Ordering::Equal); assert_eq!(Tenth(100).cmp(&Tenth(67)), Ordering::Greater); assert_eq!( Generic(SomeType { foo: 0 }).partial_cmp(&Generic(SomeType { foo: 0 })), Some(Ordering::Less) ); assert_eq!( Generic(SomeType { foo: 0 }).cmp(&Generic(SomeType { foo: 0 })), Ordering::Less ); assert_eq!( GenericIgnore { f: 123, t: PhantomData::::default() } .cmp(&GenericIgnore { f: 123, t: PhantomData::::default() }), Ordering::Equal ); assert_eq!( GenericIgnore { f: 123, t: PhantomData::::default() } .partial_cmp(&GenericIgnore { f: 123, t: PhantomData::::default() }), Some(Ordering::Equal) ); } derivative-2.2.0/tests/derive-partial-eq-packed.rs010064400362620024044000000053301400305350200203460ustar0000000000000000#![allow(clippy::eq_op, clippy::trivially_copy_pass_by_ref)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(PartialEq)] #[repr(C, packed)] struct Foo { foo: u8, } #[derive(Derivative)] #[derivative(PartialEq)] #[repr(C, packed)] struct WithPtr { #[derivative(PartialEq(bound = ""))] foo: *const T, } #[derive(Derivative)] #[derivative(PartialEq)] #[repr(C, packed)] struct Empty; #[derive(Derivative)] #[derivative(PartialEq)] #[repr(C, packed)] struct AllIgnored { #[derivative(PartialEq = "ignore")] foo: u8, } #[derive(Derivative)] #[derivative(PartialEq)] #[repr(C, packed)] struct OneIgnored { #[derivative(PartialEq = "ignore")] foo: u8, bar: u8, } #[derive(Derivative)] #[derivative(PartialEq)] #[repr(C, packed)] struct Parity(#[derivative(PartialEq(compare_with = "same_parity"))] u8); fn same_parity(lhs: &u8, rhs: &u8) -> bool { lhs % 2 == rhs % 2 } #[derive(Derivative)] #[derivative(PartialEq)] #[repr(C, packed)] struct Generic(#[derivative(PartialEq(compare_with = "dummy_cmp", bound = ""))] T); fn dummy_cmp(_: &T, _: &T) -> bool { true } struct NonPartialEq; #[derive(Derivative)] #[derivative(PartialEq, Eq)] #[repr(C, packed)] struct GenericIgnore { f: u32, #[derivative(PartialEq = "ignore")] t: T, } trait SomeTrait {} #[derive(Copy, Clone)] struct SomeType { #[allow(dead_code)] foo: u8, } impl SomeTrait for SomeType {} #[test] fn main() { assert!(Foo { foo: 7 } == Foo { foo: 7 }); assert!(Foo { foo: 7 } != Foo { foo: 42 }); let ptr1: *const dyn SomeTrait = &SomeType { foo: 0 }; let ptr2: *const dyn SomeTrait = &SomeType { foo: 1 }; assert!(WithPtr { foo: ptr1 } == WithPtr { foo: ptr1 }); assert!(WithPtr { foo: ptr1 } != WithPtr { foo: ptr2 }); assert!(Empty == Empty); assert!(AllIgnored { foo: 0 } == AllIgnored { foo: 42 }); assert!(OneIgnored { foo: 0, bar: 6 } == OneIgnored { foo: 42, bar: 6 }); assert!(OneIgnored { foo: 0, bar: 6 } != OneIgnored { foo: 42, bar: 7 }); assert!(Option::Some(42) == Option::Some(42)); assert!(Option::Some(0) != Option::Some(42)); assert!(Option::Some(42) != Option::None); assert!(Option::None != Option::Some(42)); assert!(Option::None:: == Option::None::); assert!(Parity(3) == Parity(7)); assert!(Parity(2) == Parity(42)); assert!(Parity(3) != Parity(42)); assert!(Parity(2) != Parity(7)); assert!(Generic(SomeType { foo: 0 }) == Generic(SomeType { foo: 0 })); assert!( GenericIgnore { f: 123, t: NonPartialEq } == GenericIgnore { f: 123, t: NonPartialEq } ); } derivative-2.2.0/tests/derive-partial-eq.rs010064400362620024044000000065071400305350200171300ustar0000000000000000#![allow(clippy::eq_op, clippy::trivially_copy_pass_by_ref, dead_code)] #[cfg(feature = "use_core")] extern crate core; use std::marker::PhantomData; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(PartialEq)] struct Foo { foo: u8, } /// Test for backward compatibility. #[derive(Derivative)] #[derivative(PartialEq = "feature_allow_slow_enum")] #[allow(unused)] enum AllowsFeature { Some(T), None, } #[derive(Derivative)] #[derivative(PartialEq)] enum Option { Some(T), None, } #[derive(Derivative)] #[derivative(PartialEq)] enum SimpleEnum { Some, None, } #[derive(Derivative)] #[derivative(PartialEq)] enum UnitEnum { Single, } #[derive(Derivative)] #[derivative(PartialEq)] struct WithPtr { #[derivative(PartialEq(bound = ""))] foo: *const T, } #[derive(Derivative)] #[derivative(PartialEq)] struct Empty; #[derive(Derivative)] #[derivative(PartialEq)] struct AllIgnored { #[derivative(PartialEq = "ignore")] foo: u8, } #[derive(Derivative)] #[derivative(PartialEq)] struct OneIgnored { #[derivative(PartialEq = "ignore")] foo: u8, bar: u8, } #[derive(Derivative)] #[derivative(PartialEq)] struct Parity(#[derivative(PartialEq(compare_with = "same_parity"))] u8); fn same_parity(lhs: &u8, rhs: &u8) -> bool { lhs % 2 == rhs % 2 } #[derive(Derivative)] #[derivative(PartialEq)] struct Generic(#[derivative(PartialEq(compare_with = "dummy_cmp", bound = ""))] T); fn dummy_cmp(_: &T, _: &T) -> bool { true } struct NonPartialEq; #[derive(Derivative)] #[derivative(PartialEq, Eq)] struct GenericIgnore { f: u32, #[derivative(PartialEq = "ignore")] t: PhantomData, } trait SomeTrait {} struct SomeType { #[allow(dead_code)] foo: u8, } impl SomeTrait for SomeType {} #[test] fn main() { assert!(Foo { foo: 7 } == Foo { foo: 7 }); assert!(Foo { foo: 7 } != Foo { foo: 42 }); let ptr1: *const dyn SomeTrait = &SomeType { foo: 0 }; let ptr2: *const dyn SomeTrait = &SomeType { foo: 1 }; assert!(WithPtr { foo: ptr1 } == WithPtr { foo: ptr1 }); assert!(WithPtr { foo: ptr1 } != WithPtr { foo: ptr2 }); assert!(Empty == Empty); assert!(AllIgnored { foo: 0 } == AllIgnored { foo: 42 }); assert!(OneIgnored { foo: 0, bar: 6 } == OneIgnored { foo: 42, bar: 6 }); assert!(OneIgnored { foo: 0, bar: 6 } != OneIgnored { foo: 42, bar: 7 }); assert!(Option::Some(42) == Option::Some(42)); assert!(Option::Some(0) != Option::Some(42)); assert!(Option::Some(42) != Option::None); assert!(Option::None != Option::Some(42)); assert!(Option::None:: == Option::None::); assert!(SimpleEnum::Some == SimpleEnum::Some); assert!(SimpleEnum::None == SimpleEnum::None); assert!(SimpleEnum::Some != SimpleEnum::None); assert!(SimpleEnum::None != SimpleEnum::Some); assert!(UnitEnum::Single == UnitEnum::Single); assert!(Parity(3) == Parity(7)); assert!(Parity(2) == Parity(42)); assert!(Parity(3) != Parity(42)); assert!(Parity(2) != Parity(7)); assert!(Generic(SomeType { foo: 0 }) == Generic(SomeType { foo: 0 })); assert!( GenericIgnore { f: 123, t: PhantomData::::default() } == GenericIgnore { f: 123, t: PhantomData::::default() } ); } derivative-2.2.0/tests/issue-37-turbofish.rs010064400362620024044000000003371400305350200171720ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug)] pub struct A { #[derivative(Debug(format_with = "std::fmt::Debug::fmt"))] v: u64, } derivative-2.2.0/tests/issue-55.rs010064400362620024044000000005711400305350200151670ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; trait Foo {} fn fmt(_: &T, _: &mut std::fmt::Formatter) -> std::fmt::Result { unimplemented!() } #[derive(Debug)] struct Qux<'a, T: Foo>(&'a T); #[derive(Derivative)] #[derivative(Debug)] struct _Bar<'a, T: Foo>(#[derivative(Debug(format_with="fmt"))] Qux<'a, T>); fn main() { }derivative-2.2.0/tests/issue-57.rs010064400362620024044000000004301400305350200151630ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; macro_rules! gen { ($name:ident) => { #[derive(Derivative)] #[derivative(Debug)] pub struct $name { a: i32 } }; } gen!(Test); fn main() {}derivative-2.2.0/tests/issue-58.rs010064400362620024044000000004231400305350200151660ustar0000000000000000#![deny(clippy::all)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Default, Derivative)] #[derivative(Debug)] pub struct Foo { foo: u8, } fn main() { let foo1 = Foo::default(); println!("foo = {:?}", foo1); } derivative-2.2.0/tests/issue-67.rs010064400362620024044000000002531400305350200151670ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Hash)] enum _Enumeration { _Variant(T), }derivative-2.2.0/tests/issue-82.rs010064400362620024044000000003111400305350200151570ustar0000000000000000#[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Copy, Clone, Derivative)] #[derivative(Debug)] #[repr(C, packed)] struct Test { a: u8, b: u32, }derivative-2.2.0/tests/rustc-class-implement-traits.rs010064400362620024044000000032061400305350200213450ustar0000000000000000// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(non_camel_case_types)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; trait noisy { fn speak(&mut self); } #[derive(Derivative)] #[derivative(Clone)] struct cat { meows : usize, how_hungry : isize, name : String, } impl cat { fn meow(&mut self) { println!("Meow"); self.meows += 1_usize; if self.meows % 5_usize == 0_usize { self.how_hungry += 1; } } } impl cat { pub fn eat(&mut self) -> bool { if self.how_hungry > 0 { println!("OM NOM NOM"); self.how_hungry -= 2; true } else { println!("Not hungry!"); false } } } impl noisy for cat { fn speak(&mut self) { self.meow(); } } fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { cat { meows: in_x, how_hungry: in_y, name: in_name, } } fn make_speak(mut c: C) { c.speak(); } #[test] fn main() { let mut nyan = cat(0_usize, 2, "nyan".to_string()); nyan.eat(); assert!((!nyan.eat())); for _ in 1_usize..10_usize { make_speak(nyan.clone()); } } derivative-2.2.0/tests/rustc-deriving-bounds.rs010064400362620024044000000012221400305350200200370ustar0000000000000000// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Copy, Clone)] struct Test; #[test] fn main() { let _ = Test; } derivative-2.2.0/tests/rustc-deriving-clone-array.rs010064400362620024044000000013111400305350200207600ustar0000000000000000// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // test for issue #30244 #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Copy, Clone)] #[allow(dead_code)] struct Array { arr: [[u8; 256]; 4] } #[test] fn main() {} derivative-2.2.0/tests/rustc-deriving-clone-enum.rs010064400362620024044000000014041400305350200206110ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // pretty-expanded FIXME #23616 #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Clone)] enum E { A, B(()), C, } #[test] fn main() { let _ = E::A.clone(); let _ = E::B(()).clone(); let _ = E::C.clone(); } derivative-2.2.0/tests/rustc-deriving-clone-generic-enum.rs010064400362620024044000000013731400305350200222300ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // pretty-expanded FIXME #23616 #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Clone)] #[allow(dead_code)] enum E { A(T), B(T,U), C } #[test] fn main() { let _ = E::A::(1).clone(); } derivative-2.2.0/tests/rustc-deriving-clone-generic-tuple-struct.rs010064400362620024044000000013001400305350200237250ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // pretty-expanded FIXME #23616 #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Clone)] struct S(T, ()); #[test] fn main() { let _ = S(1, ()).clone(); } derivative-2.2.0/tests/rustc-deriving-clone-struct.rs010064400362620024044000000017211400305350200211730ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // pretty-expanded FIXME #23616 #![allow(clippy::redundant_clone)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Default, Derivative)] #[derivative(Clone)] struct S { _int: isize, _i8: i8, _i16: i16, _i32: i32, _i64: i64, _uint: usize, _u8: u8, _u16: u16, _u32: u32, _u64: u64, _f32: f32, _f64: f64, _bool: bool, _char: char, _nil: () } #[test] fn main() { let _ = S::default().clone(); } derivative-2.2.0/tests/rustc-deriving-clone-tuple-struct.rs010064400362620024044000000012371400305350200223240ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // pretty-expanded FIXME #23616 #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Clone)] struct S((), ()); #[test] fn main() {} derivative-2.2.0/tests/rustc-deriving-cmp-generic-enum.rs010064400362620024044000000032131400305350200217020ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // no-pretty-expanded FIXME #15189 #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative( PartialEq = "feature_allow_slow_enum", Eq, PartialOrd = "feature_allow_slow_enum", Ord = "feature_allow_slow_enum" )] enum E { V0, V1(T), V2(T, T), } #[test] fn main() { let e0 = E::V0; let e11 = E::V1(1); let e12 = E::V1(2); let e21 = E::V2(1, 1); let e22 = E::V2(1, 2); // in order for both PartialOrd and Ord let es = [e0, e11, e12, e21, e22]; for (i, e1) in es.iter().enumerate() { for (j, e2) in es.iter().enumerate() { let ord = i.cmp(&j); let eq = i == j; let lt = i < j; let le = i <= j; let gt = i > j; let ge = i >= j; // PartialEq assert_eq!(*e1 == *e2, eq); assert_eq!(*e1 != *e2, !eq); // PartialOrd assert_eq!(*e1 < *e2, lt); assert_eq!(*e1 > *e2, gt); assert_eq!(*e1 <= *e2, le); assert_eq!(*e1 >= *e2, ge); // Ord assert_eq!(e1.cmp(e2), ord); } } } derivative-2.2.0/tests/rustc-deriving-cmp-generic-struct-enum.rs010064400362620024044000000032611400305350200232270ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // no-pretty-expanded FIXME #15189 #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative( PartialEq = "feature_allow_slow_enum", Eq, PartialOrd = "feature_allow_slow_enum", Ord = "feature_allow_slow_enum" )] enum ES { ES1 { x: T }, ES2 { x: T, y: T }, } pub fn main() { let (es11, es12, es21, es22) = ( ES::ES1 { x: 1 }, ES::ES1 { x: 2 }, ES::ES2 { x: 1, y: 1 }, ES::ES2 { x: 1, y: 2 }, ); // in order for both PartialOrd and Ord let ess = [es11, es12, es21, es22]; for (i, es1) in ess.iter().enumerate() { for (j, es2) in ess.iter().enumerate() { let ord = i.cmp(&j); let eq = i == j; let (lt, le) = (i < j, i <= j); let (gt, ge) = (i > j, i >= j); // PartialEq assert_eq!(*es1 == *es2, eq); assert_eq!(*es1 != *es2, !eq); // PartialOrd assert_eq!(*es1 < *es2, lt); assert_eq!(*es1 > *es2, gt); assert_eq!(*es1 <= *es2, le); assert_eq!(*es1 >= *es2, ge); // Ord assert_eq!(es1.cmp(es2), ord); } } } derivative-2.2.0/tests/rustc-deriving-cmp-generic-struct.rs010064400362620024044000000027121400305350200222650ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // no-pretty-expanded FIXME #15189 #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(PartialEq, Eq, PartialOrd, Ord)] struct S { x: T, y: T, } pub fn main() { let s1 = S { x: 1, y: 1 }; let s2 = S { x: 1, y: 2 }; // in order for both PartialOrd and Ord let ss = [s1, s2]; for (i, s1) in ss.iter().enumerate() { for (j, s2) in ss.iter().enumerate() { let ord = i.cmp(&j); let eq = i == j; let lt = i < j; let le = i <= j; let gt = i > j; let ge = i >= j; // PartialEq assert_eq!(*s1 == *s2, eq); assert_eq!(*s1 != *s2, !eq); // PartialOrd assert_eq!(*s1 < *s2, lt); assert_eq!(*s1 > *s2, gt); assert_eq!(*s1 <= *s2, le); assert_eq!(*s1 >= *s2, ge); // Ord assert_eq!(s1.cmp(s2), ord); } } } derivative-2.2.0/tests/rustc-deriving-cmp-generic-tuple-struct.rs010064400362620024044000000027011400305350200234120ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // no-pretty-expanded FIXME #15189 #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(PartialEq, Eq, PartialOrd, Ord)] struct TS(T, T); pub fn main() { let ts1 = TS(1, 1); let ts2 = TS(1, 2); // in order for both PartialOrd and Ord let tss = [ts1, ts2]; for (i, ts1) in tss.iter().enumerate() { for (j, ts2) in tss.iter().enumerate() { let ord = i.cmp(&j); let eq = i == j; let lt = i < j; let le = i <= j; let gt = i > j; let ge = i >= j; // PartialEq assert_eq!(*ts1 == *ts2, eq); assert_eq!(*ts1 != *ts2, !eq); // PartialOrd assert_eq!(*ts1 < *ts2, lt); assert_eq!(*ts1 > *ts2, gt); assert_eq!(*ts1 <= *ts2, le); assert_eq!(*ts1 >= *ts2, ge); // Ord assert_eq!(ts1.cmp(ts2), ord); } } } derivative-2.2.0/tests/rustc-deriving-copyclone.rs010064400362620024044000000032271400305350200205470ustar0000000000000000// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Test that #[derive(Copy, Clone)] produces a shallow copy //! even when a member violates RFC 1521 #![allow(clippy::clone_on_copy)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; use std::sync::atomic::{AtomicBool, Ordering}; /// A struct that pretends to be Copy, but actually does something /// in its Clone impl #[derive(Copy)] struct Liar; /// Static cooperating with the rogue Clone impl static CLONED: AtomicBool = AtomicBool::new(false); impl Clone for Liar { fn clone(&self) -> Self { // this makes Clone vs Copy observable CLONED.store(true, Ordering::SeqCst); *self } } /// This struct is actually Copy... at least, it thinks it is! #[derive(Copy, Clone)] struct TheirTheir(Liar); #[derive(Derivative)] #[derivative(Copy, Clone)] struct OurOur1(Liar); #[derive(Derivative)] #[derivative(Clone, Copy)] struct OurOur2(Liar); #[test] fn main() { let _ = TheirTheir(Liar).clone(); assert!(!CLONED.load(Ordering::SeqCst), "TheirTheir"); let _ = OurOur1(Liar).clone(); assert!(!CLONED.load(Ordering::SeqCst), "OurOur1"); let _ = OurOur2(Liar).clone(); assert!(!CLONED.load(Ordering::SeqCst), "OurOur2"); } derivative-2.2.0/tests/rustc-deriving-default-box.rs010064400362620024044000000014411400305350200207620ustar0000000000000000// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; use std::default::Default; #[derive(Derivative)] #[derivative(Default)] struct A { foo: Box<[bool]>, } #[test] fn main() { let a: A = Default::default(); let b: Box<[_]> = Box::<[bool; 0]>::new([]); assert_eq!(a.foo, b); } derivative-2.2.0/tests/rustc-deriving-enum-single-variant.rs010064400362620024044000000014211400305350200224330ustar0000000000000000// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // pretty-expanded FIXME #23616 #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; pub type TaskId = isize; #[derive(Derivative)] #[derivative(PartialEq="feature_allow_slow_enum")] pub enum Task { TaskHandle(TaskId) } #[test] fn main() { let _ = Task::TaskHandle(42); } derivative-2.2.0/tests/rustc-deriving-hash.rs010064400362620024044000000037121400305350200174760ustar0000000000000000// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(non_camel_case_types)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; use std::hash::{Hash, Hasher}; use std::collections::hash_map::DefaultHasher; #[derive(Derivative)] #[derivative(Hash)] struct Person { id: u16, name: String, phone: u64, } // test for hygiene name collisions #[derive(Derivative)] #[derivative(Hash)] struct __H__H; #[derive(Derivative)] #[allow(dead_code)] #[derivative(Hash)] struct Collision<__H> ( __H ); // TODO(rustc) #[derivative(Hash)] enum Collision<__H> { __H { __H__H: __H } } #[derive(Derivative)] #[derivative(Hash)] enum E { A=1, B } fn hash(t: &T) -> u64 { let mut s = DefaultHasher::new(); t.hash(&mut s); s.finish() } struct FakeHasher<'a>(&'a mut Vec); impl<'a> Hasher for FakeHasher<'a> { fn finish(&self) -> u64 { unimplemented!() } fn write(&mut self, bytes: &[u8]) { self.0.extend(bytes); } } fn fake_hash(v: &mut Vec, e: E) { e.hash(&mut FakeHasher(v)); } #[test] fn main() { let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_777, }; let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_777, }; assert_eq!(hash(&person1), hash(&person1)); assert!(hash(&person1) != hash(&person2)); // test #21714 let mut va = vec![]; let mut vb = vec![]; fake_hash(&mut va, E::A); fake_hash(&mut vb, E::B); assert!(va != vb); } derivative-2.2.0/tests/rustc-deriving-in-fn.rs010064400362620024044000000013251400305350200175600ustar0000000000000000// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[test] fn main() { #[derive(Derivative)] #[derivative(Debug)] struct Foo { foo: isize, } let f = Foo { foo: 10 }; format!("{:?}", f); } derivative-2.2.0/tests/rustc-deriving-meta-multiple.rs010064400362620024044000000022051400305350200213260ustar0000000000000000// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // pretty-expanded FIXME #23616 #![allow(clippy::eq_op, clippy::redundant_clone)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; use std::hash::Hash; // testing multiple separate deriving attributes #[derive(Derivative)] #[derivative(PartialEq)] #[derivative(Clone)] #[derivative(Hash)] struct Foo { bar: usize, baz: isize } fn hash(_t: &T) {} #[test] fn main() { let a = Foo {bar: 4, baz: -3}; let _ = a == a; // check for PartialEq impl w/o testing its correctness let _ = a.clone(); // check for Clone impl w/o testing its correctness hash(&a); // check for Hash impl w/o testing its correctness } derivative-2.2.0/tests/rustc-deriving-meta.rs010064400362620024044000000020701400305350200174750ustar0000000000000000// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // pretty-expanded FIXME #23616 #![allow(clippy::eq_op, clippy::redundant_clone)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; use std::hash::Hash; #[derive(Derivative)] #[derivative(PartialEq, Clone, Hash)] struct Foo { bar: usize, baz: isize } fn hash(_t: &T) {} #[test] fn main() { let a = Foo {bar: 4, baz: -3}; let _ = a == a; // check for PartialEq impl w/o testing its correctness let _ = a.clone(); // check for Clone impl w/o testing its correctness hash(&a); // check for Hash impl w/o testing its correctness } derivative-2.2.0/tests/rustc-deriving-show-2.rs010064400362620024044000000033371400305350200176750ustar0000000000000000#![allow(dead_code)] #![deny(unused_variables)] // We used to generate warning: unused variable: `f` #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; use std::fmt; #[derive(Derivative)] #[derivative(Debug)] enum A {} #[derive(Derivative)] #[derivative(Debug)] enum B { V1, V2, V3 } #[derive(Derivative)] #[derivative(Debug)] enum C { V1(isize), V2(B), V3(String) } #[derive(Derivative)] #[derivative(Debug)] enum D { V1{ a: isize } } #[derive(Derivative)] #[derivative(Debug)] struct E; #[derive(Derivative)] #[derivative(Debug)] struct F(isize); #[derive(Derivative)] #[derivative(Debug)] struct G(isize, isize); #[derive(Derivative)] #[derivative(Debug)] struct H { a: isize } #[derive(Derivative)] #[derivative(Debug)] struct I { a: isize, b: isize } #[derive(Derivative)] #[derivative(Debug)] struct J(Custom); struct Custom; impl fmt::Debug for Custom { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "yay") } } trait ToDebug { fn to_show(&self) -> String; } impl ToDebug for T { fn to_show(&self) -> String { format!("{:?}", self) } } #[test] fn main() { assert_eq!(B::V1.to_show(), "V1".to_string()); assert_eq!(B::V2.to_show(), "V2".to_string()); assert_eq!(C::V1(3).to_show(), "V1(3)".to_string()); assert_eq!(C::V2(B::V2).to_show(), "V2(V2)".to_string()); assert_eq!(D::V1{ a: 2 }.to_show(), "V1 { a: 2 }".to_string()); assert_eq!(E.to_show(), "E".to_string()); assert_eq!(F(3).to_show(), "F(3)".to_string()); assert_eq!(G(3, 4).to_show(), "G(3, 4)".to_string()); assert_eq!(I{ a: 2, b: 4 }.to_show(), "I { a: 2, b: 4 }".to_string()); assert_eq!(J(Custom).to_show(), "J(yay)".to_string()); } derivative-2.2.0/tests/rustc-deriving-show.rs010064400362620024044000000024511400305350200175320ustar0000000000000000// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug)] struct Unit; #[derive(Derivative)] #[derivative(Debug)] struct Tuple(isize, usize); #[derive(Derivative)] #[derivative(Debug)] struct Struct { x: isize, y: usize } #[derive(Derivative)] #[derivative(Debug)] enum Enum { Nullary, Variant(isize, usize), StructVariant { x: isize, y : usize } } macro_rules! t { ($x:expr, $expected:expr) => { assert_eq!(format!("{:?}", $x), $expected.to_string()) } } #[test] fn main() { t!(Unit, "Unit"); t!(Tuple(1, 2), "Tuple(1, 2)"); t!(Struct { x: 1, y: 2 }, "Struct { x: 1, y: 2 }"); t!(Enum::Nullary, "Nullary"); t!(Enum::Variant(1, 2), "Variant(1, 2)"); t!(Enum::StructVariant { x: 1, y: 2 }, "StructVariant { x: 1, y: 2 }"); } derivative-2.2.0/tests/rustc-deriving-via-extension-hash-enum.rs010064400362620024044000000014401400305350200232230ustar0000000000000000// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Hash)] #[allow(dead_code)] enum Foo { Bar(isize, char), Baz(char, isize) } #[derive(Derivative)] #[derivative(Hash)] #[allow(dead_code)] enum A { B, C, D, E } #[test] fn main(){} derivative-2.2.0/tests/rustc-deriving-via-extension-hash-struct.rs010064400362620024044000000015561400305350200236130ustar0000000000000000// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // pretty-expanded FIXME #23616 #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; use std::collections::hash_map::DefaultHasher; #[derive(Derivative)] #[derivative(Hash)] struct Foo { x: isize, y: isize, z: isize } #[test] fn main() { use std::hash::Hash; let mut hasher = DefaultHasher::new(); Foo { x: 0, y: 0, z: 0 }.hash(&mut hasher); } derivative-2.2.0/tests/rustc-deriving-via-extension-type-params.rs010064400362620024044000000015551400305350200236070ustar0000000000000000// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(PartialEq, Hash, Debug)] struct Foo { x: isize, y: T, z: isize } #[test] fn main() { let a = Foo { x: 1, y: 2.0f64, z: 3 }; let b = Foo { x: 1, y: 2.0f64, z: 3 }; assert_eq!(a, b); assert!(!(a != b)); assert!(a.eq(&b)); assert!(!a.ne(&b)); } derivative-2.2.0/tests/rustc-expr-copy.rs010064400362620024044000000015041400305350200166710ustar0000000000000000// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; fn f(arg: &mut A) { arg.a = 100; } #[derive(Derivative)] #[derivative(Copy, Clone)] struct A { a: isize } #[test] fn main() { let mut x = A {a: 10}; f(&mut x); assert_eq!(x.a, 100); x.a = 20; let mut y = x; f(&mut y); assert_eq!(x.a, 20); } derivative-2.2.0/tests/rustc-exterior.rs010064400362620024044000000021401400305350200166010ustar0000000000000000// Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; use std::cell::Cell; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Copy, Clone)] struct Point {x: isize, y: isize, z: isize} fn f(p: &Cell) { assert_eq!(p.get().z, 12); p.set(Point {x: 10, y: 11, z: 13}); assert_eq!(p.get().z, 13); } #[test] fn main() { let a: Point = Point {x: 10, y: 11, z: 12}; let b: &Cell = &Cell::new(a); assert_eq!(b.get().z, 12); f(b); assert_eq!(a.x, 10); assert_eq!(a.y, 11); assert_eq!(a.z, 12); assert_eq!(b.get().x, 10); assert_eq!(b.get().y, 11); assert_eq!(b.get().z, 13); } derivative-2.2.0/tests/rustc-issue-12860.rs010064400362620024044000000037161400305350200165600ustar0000000000000000// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(clippy::derive_hash_xor_eq)] #[cfg(feature = "use_core")] extern crate core; use std::collections::HashSet; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Hash)] #[derive(Copy, Clone, PartialEq, Eq)] struct XYZ { x: isize, y: isize, z: isize } #[test] fn main() { let mut connected = HashSet::new(); let mut border = HashSet::new(); let middle = XYZ{x: 0, y: 0, z: 0}; border.insert(middle); while !border.is_empty() && connected.len() < 10000 { let choice = *(border.iter().next().unwrap()); border.remove(&choice); connected.insert(choice); let cxp = XYZ{x: choice.x + 1, y: choice.y, z: choice.z}; let cxm = XYZ{x: choice.x - 1, y: choice.y, z: choice.z}; let cyp = XYZ{x: choice.x, y: choice.y + 1, z: choice.z}; let cym = XYZ{x: choice.x, y: choice.y - 1, z: choice.z}; let czp = XYZ{x: choice.x, y: choice.y, z: choice.z + 1}; let czm = XYZ{x: choice.x, y: choice.y, z: choice.z - 1}; if !connected.contains(&cxp) { border.insert(cxp); } if !connected.contains(&cxm){ border.insert(cxm); } if !connected.contains(&cyp){ border.insert(cyp); } if !connected.contains(&cym) { border.insert(cym); } if !connected.contains(&czp){ border.insert(czp); } if !connected.contains(&czm) { border.insert(czm); } } } derivative-2.2.0/tests/rustc-issue-13434.rs010064400362620024044000000017001400305350200165450ustar0000000000000000// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug)] struct MyStruct; trait Repro { fn repro(self, s: MyStruct) -> String; } impl Repro for F where F: FnOnce(MyStruct) -> String { fn repro(self, s: MyStruct) -> String { self(s) } } fn do_stuff(r: R) -> String { r.repro(MyStruct) } #[test] fn main() { assert_eq!("MyStruct".to_string(), do_stuff(|s: MyStruct| format!("{:?}", s))); } derivative-2.2.0/tests/rustc-issue-16530.rs010064400362620024044000000015721400305350200165540ustar0000000000000000// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(deprecated)] #[cfg(feature = "use_core")] extern crate core; use std::hash::{SipHasher, Hasher, Hash}; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Hash)] struct Empty; #[test] fn main() { let mut s1 = SipHasher::new_with_keys(0, 0); Empty.hash(&mut s1); let mut s2 = SipHasher::new_with_keys(0, 0); Empty.hash(&mut s2); assert_eq!(s1.finish(), s2.finish()); } derivative-2.2.0/tests/rustc-issue-19037.rs010064400362620024044000000015661400305350200165640ustar0000000000000000// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // pretty-expanded FIXME #23616 #![allow(dead_code)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; struct Str([u8]); #[derive(Derivative)] #[derivative(Clone)] struct CharSplits<'a, Sep> { string: &'a Str, sep: Sep, allow_trailing_empty: bool, only_ascii: bool, finished: bool, } fn clone(s: &Str) -> &Str { Clone::clone(&s) } #[test] fn main() {} derivative-2.2.0/tests/rustc-issue-19102.rs010064400362620024044000000013011400305350200165400ustar0000000000000000// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![deny(unused_qualifications)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(PartialEq="feature_allow_slow_enum")] pub enum A { B, } #[test] fn main() {} derivative-2.2.0/tests/rustc-issue-19135.rs010064400362620024044000000015371400305350200165610ustar0000000000000000// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; use std::marker::PhantomData; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug)] struct LifetimeStruct<'a>(PhantomData<&'a ()>); #[test] fn main() { takes_hrtb_closure(|lts| println!("{:?}", lts)); } fn takes_hrtb_closureFnMut(LifetimeStruct<'a>)>(mut f: F) { f(LifetimeStruct(PhantomData)); } derivative-2.2.0/tests/rustc-issue-19358.rs010064400362620024044000000016041400305350200165630ustar0000000000000000// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; trait Trait { fn dummy(&self) { } } #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug)] struct Foo { foo: T, } #[derive(Derivative)] #[derivative(Debug)] struct Bar where T: Trait { bar: T, } impl Trait for isize {} #[test] fn main() { let a = Foo { foo: 12 }; let b = Bar { bar: 12 }; println!("{:?} {:?}", a, b); } derivative-2.2.0/tests/rustc-issue-21402.rs010064400362620024044000000013501400305350200165400ustar0000000000000000// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // pretty-expanded FIXME #23616 #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Hash)] #[allow(dead_code)] struct Foo { a: Vec, b: (bool, bool), c: [bool; 2], } #[test] fn main() {} derivative-2.2.0/tests/rustc-issue-23649-3.rs010064400362620024044000000012411400305350200167160ustar0000000000000000// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[allow(dead_code)] #[derive(Derivative)] #[derivative(PartialEq)] struct Slice { slice: [u8] } #[test] fn main() {} derivative-2.2.0/tests/rustc-issue-24085.rs010064400362620024044000000021451400305350200165550ustar0000000000000000// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Regression test for #24085. Errors were occurring in region // inference due to the requirement that `'a:b'`, which was getting // incorrectly translated in connection with the closure below. #![allow(clippy::redundant_closure)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Copy,Clone)] #[allow(dead_code)] struct Path<'a:'b, 'b> { x: &'a i32, tail: Option<&'b Path<'a, 'b>> } #[allow(dead_code, unconditional_recursion)] fn foo<'a,'b,F>(p: Path<'a, 'b>, mut f: F) where F: for<'c> FnMut(Path<'a, 'c>) { foo(p, |x| f(x)) } #[test] fn main() { } derivative-2.2.0/tests/rustc-issue-25394.rs010064400362620024044000000012621400305350200165600ustar0000000000000000// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug)] struct Row([T]); fn use_row(_: &Row) {} #[test] fn main() { let _ = use_row; } derivative-2.2.0/tests/rustc-issue-28561.rs010064400362620024044000000062071400305350200165630ustar0000000000000000// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(clippy::zero_prefixed_literal, clippy::type_complexity)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug, Default, Eq, Hash, PartialEq)] // TODO: Ord, PartialOrd struct Array { f00: [T; 00], f01: [T; 01], f02: [T; 02], f03: [T; 03], f04: [T; 04], f05: [T; 05], f06: [T; 06], f07: [T; 07], f08: [T; 08], f09: [T; 09], f10: [T; 10], f11: [T; 11], f12: [T; 12], f13: [T; 13], f14: [T; 14], f15: [T; 15], f16: [T; 16], f17: [T; 17], f18: [T; 18], f19: [T; 19], f20: [T; 20], f21: [T; 21], f22: [T; 22], f23: [T; 23], f24: [T; 24], f25: [T; 25], f26: [T; 26], f27: [T; 27], f28: [T; 28], f29: [T; 29], f30: [T; 30], f31: [T; 31], f32: [T; 32], } // FIXME(#7622): merge with `Array` once `[T; N]: Clone` where `T: Clone` #[derive(Derivative)] #[derivative(Clone, Copy)] struct CopyArray { f00: [T; 00], f01: [T; 01], f02: [T; 02], f03: [T; 03], f04: [T; 04], f05: [T; 05], f06: [T; 06], f07: [T; 07], f08: [T; 08], f09: [T; 09], f10: [T; 10], f11: [T; 11], f12: [T; 12], f13: [T; 13], f14: [T; 14], f15: [T; 15], f16: [T; 16], f17: [T; 17], f18: [T; 18], f19: [T; 19], f20: [T; 20], f21: [T; 21], f22: [T; 22], f23: [T; 23], f24: [T; 24], f25: [T; 25], f26: [T; 26], f27: [T; 27], f28: [T; 28], f29: [T; 29], f30: [T; 30], f31: [T; 31], f32: [T; 32], } #[derive(Derivative)] #[derivative(Clone, Copy, Debug, Eq, Hash, PartialEq)] // TODO: Ord, PartialOrd struct Fn { f00: fn(), f01: fn(A), f02: fn(A, B), f03: fn(A, B, C), f04: fn(A, B, C, D), f05: fn(A, B, C, D, E), f06: fn(A, B, C, D, E, F), f07: fn(A, B, C, D, E, F, G), f08: fn(A, B, C, D, E, F, G, H), f09: fn(A, B, C, D, E, F, G, H, I), f10: fn(A, B, C, D, E, F, G, H, I, J), f11: fn(A, B, C, D, E, F, G, H, I, J, K), f12: fn(A, B, C, D, E, F, G, H, I, J, K, L), } #[derive(Derivative)] #[derivative(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)] // TODO: Ord, PartialOrd struct Tuple { f00: (), f01: (A,), f02: (A, B), f03: (A, B, C), f04: (A, B, C, D), f05: (A, B, C, D, E), f06: (A, B, C, D, E, F), f07: (A, B, C, D, E, F, G), f08: (A, B, C, D, E, F, G, H), f09: (A, B, C, D, E, F, G, H, I), f10: (A, B, C, D, E, F, G, H, I, J), f11: (A, B, C, D, E, F, G, H, I, J, K), f12: (A, B, C, D, E, F, G, H, I, J, K, L), } #[test] fn main() {} derivative-2.2.0/tests/rustc-issue-29030.rs010064400362620024044000000014061400305350200165470ustar0000000000000000// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug)] struct Message<'a, P: 'a = &'a [u8]> { header: &'a [u8], payload: P, } #[test] fn main() { let _ = Message { header: &[1], payload: &[1], }; } derivative-2.2.0/tests/rustc-issue-29540.rs010064400362620024044000000455701400305350200165670ustar0000000000000000// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug)] pub struct Config { pub name: String, pub cluster: String, pub debug_none: String, pub debug_lockdep: String, pub debug_context: String, pub debug_crush: String, pub debug_mds: String, pub debug_mds_balancer: String, pub debug_mds_locker: String, pub debug_mds_log: String, pub debug_mds_log_expire: String, pub debug_mds_migrator: String, pub debug_buffer: String, pub debug_timer: String, pub debug_filer: String, pub debug_striper: String, pub debug_objecter: String, pub debug_rados: String, pub debug_rbd: String, pub debug_journaler: String, pub debug_objectcacher: String, pub debug_client: String, pub debug_osd: String, pub debug_optracker: String, pub debug_objclass: String, pub debug_filestore: String, pub debug_keyvaluestore: String, pub debug_journal: String, pub debug_ms: String, pub debug_mon: String, pub debug_monc: String, pub debug_paxos: String, pub debug_tp: String, pub debug_auth: String, pub debug_crypto: String, pub debug_finisher: String, pub debug_heartbeatmap: String, pub debug_perfcounter: String, pub debug_rgw: String, pub debug_civetweb: String, pub debug_javaclient: String, pub debug_asok: String, pub debug_throttle: String, pub host: String, pub fsid: String, pub public_addr: String, pub cluster_addr: String, pub public_network: String, pub cluster_network: String, pub num_client: String, pub monmap: String, pub mon_host: String, pub lockdep: String, pub run_dir: String, pub admin_socket: String, pub daemonize: String, pub pid_file: String, pub chdir: String, pub max_open_files: String, pub restapi_log_level: String, pub restapi_base_url: String, pub fatal_signal_handlers: String, pub log_file: String, pub log_max_new: String, pub log_max_recent: String, pub log_to_stderr: String, pub err_to_stderr: String, pub log_to_syslog: String, pub err_to_syslog: String, pub log_flush_on_exit: String, pub log_stop_at_utilization: String, pub clog_to_monitors: String, pub clog_to_syslog: String, pub clog_to_syslog_level: String, pub clog_to_syslog_facility: String, pub mon_cluster_log_to_syslog: String, pub mon_cluster_log_to_syslog_level: String, pub mon_cluster_log_to_syslog_facility: String, pub mon_cluster_log_file: String, pub mon_cluster_log_file_level: String, pub key: String, pub keyfile: String, pub keyring: String, pub heartbeat_interval: String, pub heartbeat_file: String, pub heartbeat_inject_failure: String, pub perf: String, pub ms_tcp_nodelay: String, pub ms_tcp_rcvbuf: String, pub ms_initial_backoff: String, pub ms_max_backoff: String, pub ms_nocrc: String, pub ms_die_on_bad_msg: String, pub ms_die_on_unhandled_msg: String, pub ms_die_on_old_message: String, pub ms_dispatch_throttle_bytes: String, pub ms_bind_ipv6: String, pub ms_bind_port_min: String, pub ms_bind_port_max: String, pub ms_rwthread_stack_bytes: String, pub ms_tcp_read_timeout: String, pub ms_pq_max_tokens_per_priority: String, pub ms_pq_min_cost: String, pub ms_inject_socket_failures: String, pub ms_inject_delay_type: String, pub ms_inject_delay_msg_type: String, pub ms_inject_delay_max: String, pub ms_inject_delay_probability: String, pub ms_inject_internal_delays: String, pub ms_dump_on_send: String, pub inject_early_sigterm: String, pub mon_data: String, pub mon_initial_members: String, pub mon_sync_fs_threshold: String, pub mon_compact_on_start: String, pub mon_compact_on_bootstrap: String, pub mon_compact_on_trim: String, pub mon_tick_interval: String, pub mon_subscribe_interval: String, pub mon_delta_reset_interval: String, pub mon_osd_laggy_halflife: String, pub mon_osd_laggy_weight: String, pub mon_osd_adjust_heartbeat_grace: String, pub mon_osd_adjust_down_out_interval: String, pub mon_osd_auto_mark_in: String, pub mon_osd_auto_mark_auto_out_in: String, pub mon_osd_auto_mark_new_in: String, pub mon_osd_down_out_interval: String, pub mon_osd_down_out_subtree_limit: String, pub mon_osd_min_up_ratio: String, pub mon_osd_min_in_ratio: String, pub mon_osd_max_op_age: String, pub mon_osd_max_split_count: String, pub mon_osd_allow_primary_temp: String, pub mon_osd_allow_primary_affinity: String, pub mon_stat_smooth_intervals: String, pub mon_lease: String, pub mon_lease_renew_interval: String, pub mon_lease_ack_timeout: String, pub mon_clock_drift_allowed: String, pub mon_clock_drift_warn_backoff: String, pub mon_timecheck_interval: String, pub mon_accept_timeout: String, pub mon_pg_create_interval: String, pub mon_pg_stuck_threshold: String, pub mon_pg_warn_min_per_osd: String, pub mon_pg_warn_max_object_skew: String, pub mon_pg_warn_min_objects: String, pub mon_pg_warn_min_pool_objects: String, pub mon_cache_target_full_warn_ratio: String, pub mon_osd_full_ratio: String, pub mon_osd_nearfull_ratio: String, pub mon_globalid_prealloc: String, pub mon_osd_report_timeout: String, pub mon_force_standby_active: String, pub mon_warn_on_old_mons: String, pub mon_warn_on_legacy_crush_tunables: String, pub mon_warn_on_osd_down_out_interval_zero: String, pub mon_warn_on_cache_pools_without_hit_sets: String, pub mon_min_osdmap_epochs: String, pub mon_max_pgmap_epochs: String, pub mon_max_log_epochs: String, pub mon_max_mdsmap_epochs: String, pub mon_max_osd: String, pub mon_probe_timeout: String, pub mon_slurp_timeout: String, pub mon_slurp_bytes: String, pub mon_client_bytes: String, pub mon_daemon_bytes: String, pub mon_max_log_entries_per_event: String, pub mon_health_data_update_interval: String, pub mon_data_avail_crit: String, pub mon_data_avail_warn: String, pub mon_config_key_max_entry_size: String, pub mon_sync_timeout: String, pub mon_sync_max_payload_size: String, pub mon_sync_debug: String, pub mon_sync_debug_leader: String, pub mon_sync_debug_provider: String, pub mon_sync_debug_provider_fallback: String, pub mon_inject_sync_get_chunk_delay: String, pub mon_osd_min_down_reporters: String, pub mon_osd_min_down_reports: String, pub mon_osd_force_trim_to: String, pub mon_mds_force_trim_to: String, pub mon_advanced_debug_mode: String, pub mon_debug_dump_transactions: String, pub mon_debug_dump_location: String, pub mon_sync_provider_kill_at: String, pub mon_sync_requester_kill_at: String, pub mon_leveldb_write_buffer_size: String, pub mon_leveldb_cache_size: String, pub mon_leveldb_block_size: String, pub mon_leveldb_bloom_size: String, pub mon_leveldb_max_open_files: String, pub mon_leveldb_compression: String, pub mon_leveldb_paranoid: String, pub mon_leveldb_log: String, pub mon_leveldb_size_warn: String, pub mon_force_quorum_join: String, pub paxos_stash_full_interval: String, pub paxos_max_join_drift: String, pub paxos_propose_interval: String, pub paxos_min_wait: String, pub paxos_min: String, pub paxos_trim_min: String, pub paxos_trim_max: String, pub paxos_service_trim_min: String, pub paxos_service_trim_max: String, pub paxos_kill_at: String, pub clock_offset: String, pub auth_cluster_required: String, pub auth_service_required: String, pub auth_client_required: String, pub auth_supported: String, pub cephx_require_signatures: String, pub cephx_cluster_require_signatures: String, pub cephx_service_require_signatures: String, pub cephx_sign_messages: String, pub auth_mon_ticket_ttl: String, pub auth_service_ticket_ttl: String, pub auth_debug: String, pub mon_client_hunt_interval: String, pub mon_client_ping_interval: String, pub mon_client_ping_timeout: String, pub mon_client_hunt_interval_backoff: String, pub mon_client_hunt_interval_max_multiple: String, pub mon_client_max_log_entries_per_message: String, pub mon_max_pool_pg_num: String, pub mon_pool_quota_warn_threshold: String, pub mon_pool_quota_crit_threshold: String, pub client_cache_size: String, pub client_cache_mid: String, pub client_use_random_mds: String, pub client_mount_timeout: String, pub client_tick_interval: String, pub client_trace: String, pub client_readahead_min: String, pub client_readahead_max_bytes: String, pub client_readahead_max_periods: String, pub client_snapdir: String, pub client_mountpoint: String, pub client_notify_timeout: String, pub osd_client_watch_timeout: String, pub client_caps_release_delay: String, pub client_oc: String, pub client_oc_size: String, pub client_oc_max_dirty: String, pub client_oc_target_dirty: String, pub client_oc_max_dirty_age: String, pub client_oc_max_objects: String, pub client_debug_force_sync_read: String, pub client_debug_inject_tick_delay: String, pub client_max_inline_size: String, pub fuse_use_invalidate_cb: String, pub fuse_allow_other: String, pub fuse_default_permissions: String, pub fuse_big_writes: String, pub fuse_atomic_o_trunc: String, pub fuse_debug: String, pub fuse_multithreaded: String, pub crush_location: String, pub objecter_tick_interval: String, pub objecter_timeout: String, pub objecter_inflight_op_bytes: String, pub objecter_inflight_ops: String, pub journaler_allow_split_entries: String, pub journaler_write_head_interval: String, pub journaler_prefetch_periods: String, pub journaler_prezero_periods: String, pub journaler_batch_interval: String, pub journaler_batch_max: String, pub mds_data: String, pub mds_max_file_size: String, pub mds_cache_size: String, pub mds_cache_mid: String, pub mds_mem_max: String, pub mds_dir_max_commit_size: String, pub mds_decay_halflife: String, pub mds_beacon_interval: String, pub mds_beacon_grace: String, pub mds_enforce_unique_name: String, pub mds_blacklist_interval: String, pub mds_session_timeout: String, pub mds_freeze_tree_timeout: String, pub mds_session_autoclose: String, pub mds_reconnect_timeout: String, pub mds_tick_interval: String, pub mds_dirstat_min_interval: String, pub mds_scatter_nudge_interval: String, pub mds_client_prealloc_inos: String, pub mds_early_reply: String, pub mds_default_dir_hash: String, pub mds_log: String, pub mds_log_skip_corrupt_events: String, pub mds_log_max_events: String, pub mds_log_segment_size: String, pub mds_log_max_segments: String, pub mds_log_max_expiring: String, pub mds_bal_sample_interval: String, pub mds_bal_replicate_threshold: String, pub mds_bal_unreplicate_threshold: String, pub mds_bal_frag: String, pub mds_bal_split_size: String, pub mds_bal_split_rd: String, pub mds_bal_split_wr: String, pub mds_bal_split_bits: String, pub mds_bal_merge_size: String, pub mds_bal_merge_rd: String, pub mds_bal_merge_wr: String, pub mds_bal_interval: String, pub mds_bal_fragment_interval: String, pub mds_bal_idle_threshold: String, pub mds_bal_max: String, pub mds_bal_max_until: String, pub mds_bal_mode: String, pub mds_bal_min_rebalance: String, pub mds_bal_min_start: String, pub mds_bal_need_min: String, pub mds_bal_need_max: String, pub mds_bal_midchunk: String, pub mds_bal_minchunk: String, pub mds_bal_target_removal_min: String, pub mds_bal_target_removal_max: String, pub mds_replay_interval: String, pub mds_shutdown_check: String, pub mds_thrash_exports: String, pub mds_thrash_fragments: String, pub mds_dump_cache_on_map: String, pub mds_dump_cache_after_rejoin: String, pub mds_verify_scatter: String, pub mds_debug_scatterstat: String, pub mds_debug_frag: String, pub mds_debug_auth_pins: String, pub mds_debug_subtrees: String, pub mds_kill_mdstable_at: String, pub mds_kill_export_at: String, pub mds_kill_import_at: String, pub mds_kill_link_at: String, pub mds_kill_rename_at: String, pub mds_kill_openc_at: String, pub mds_kill_journal_at: String, pub mds_kill_journal_expire_at: String, pub mds_kill_journal_replay_at: String, pub mds_kill_create_at: String, pub mds_open_remote_link_mode: String, pub mds_inject_traceless_reply_probability: String, pub mds_wipe_sessions: String, pub mds_wipe_ino_prealloc: String, pub mds_skip_ino: String, pub max_mds: String, pub mds_standby_for_name: String, pub mds_standby_for_rank: String, pub mds_standby_replay: String, pub osd_compact_leveldb_on_mount: String, pub osd_max_backfills: String, pub osd_backfill_full_ratio: String, pub osd_backfill_retry_interval: String, pub osd_agent_max_ops: String, pub osd_agent_min_evict_effort: String, pub osd_agent_quantize_effort: String, pub osd_agent_delay_time: String, pub osd_agent_hist_halflife: String, pub osd_agent_slop: String, pub osd_uuid: String, pub osd_data: String, pub osd_journal: String, pub osd_journal_size: String, pub osd_max_write_size: String, pub osd_max_pgls: String, pub osd_client_message_size_cap: String, pub osd_client_message_cap: String, pub osd_pg_bits: String, pub osd_pgp_bits: String, pub osd_crush_chooseleaf_type: String, pub osd_pool_default_crush_rule: String, pub osd_pool_default_crush_replicated_ruleset: String, pub osd_pool_erasure_code_stripe_width: String, pub osd_pool_default_size: String, pub osd_pool_default_min_size: String, pub osd_pool_default_pg_num: String, pub osd_pool_default_pgp_num: String, pub osd_pool_default_erasure_code_directory: String, pub osd_pool_default_erasure_code_profile: String, pub osd_erasure_code_plugins: String, pub osd_pool_default_flags: String, pub osd_pool_default_flag_hashpspool: String, pub osd_pool_default_hit_set_bloom_fpp: String, pub osd_pool_default_cache_target_dirty_ratio: String, pub osd_pool_default_cache_target_full_ratio: String, pub osd_pool_default_cache_min_flush_age: String, pub osd_pool_default_cache_min_evict_age: String, pub osd_hit_set_min_size: String, pub osd_hit_set_max_size: String, pub osd_hit_set_namespace: String, pub osd_tier_default_cache_mode: String, pub osd_tier_default_cache_hit_set_count: String, pub osd_tier_default_cache_hit_set_period: String, pub osd_tier_default_cache_hit_set_type: String, pub osd_map_dedup: String, pub osd_map_max_advance: String, pub osd_map_cache_size: String, pub osd_map_message_max: String, pub osd_map_share_max_epochs: String, pub osd_op_threads: String, pub osd_peering_wq_batch_size: String, pub osd_op_pq_max_tokens_per_priority: String, pub osd_op_pq_min_cost: String, pub osd_disk_threads: String, pub osd_disk_thread_ioprio_class: String, pub osd_disk_thread_ioprio_priority: String, pub osd_recovery_threads: String, pub osd_recover_clone_overlap: String, pub osd_recover_clone_overlap_limit: String, pub osd_backfill_scan_min: String, pub osd_backfill_scan_max: String, pub osd_op_thread_timeout: String, pub osd_recovery_thread_timeout: String, pub osd_snap_trim_thread_timeout: String, pub osd_snap_trim_sleep: String, pub osd_scrub_thread_timeout: String, pub osd_scrub_finalize_thread_timeout: String, pub osd_scrub_invalid_stats: String, pub osd_remove_thread_timeout: String, pub osd_command_thread_timeout: String, pub osd_age: String, pub osd_age_time: String, pub osd_heartbeat_addr: String, pub osd_heartbeat_interval: String, pub osd_heartbeat_grace: String, pub osd_heartbeat_min_peers: String, pub osd_pg_max_concurrent_snap_trims: String, pub osd_heartbeat_min_healthy_ratio: String, pub osd_mon_heartbeat_interval: String, pub osd_mon_report_interval_max: String, pub osd_mon_report_interval_min: String, pub osd_pg_stat_report_interval_max: String, pub osd_mon_ack_timeout: String, pub osd_default_data_pool_replay_window: String, pub osd_preserve_trimmed_log: String, pub osd_auto_mark_unfound_lost: String, pub osd_recovery_delay_start: String, pub osd_recovery_max_active: String, pub osd_recovery_max_single_start: String, pub osd_recovery_max_chunk: String, pub osd_copyfrom_max_chunk: String, pub osd_push_per_object_cost: String, pub osd_max_push_cost: String, pub osd_max_push_objects: String, pub osd_recovery_forget_lost_objects: String, pub osd_max_scrubs: String, pub osd_scrub_load_threshold: String, pub osd_scrub_min_interval: String, pub osd_scrub_max_interval: String, pub osd_scrub_chunk_min: String, pub osd_scrub_chunk_max: String, pub osd_scrub_sleep: String, pub osd_deep_scrub_interval: String, pub osd_deep_scrub_stride: String, pub osd_scan_list_ping_tp_interval: String, pub osd_auto_weight: String, pub osd_class_dir: String, pub osd_open_classes_on_start: String, pub osd_check_for_log_corruption: String, pub osd_use_stale_snap: String, pub osd_rollback_to_cluster_snap: String, pub osd_default_notify_timeout: String, pub osd_kill_backfill_at: String, pub osd_pg_epoch_persisted_max_stale: String, pub osd_min_pg_log_entries: String, pub osd_max_pg_log_entries: String, pub osd_op_complaint_time: String, pub osd_command_max_records: String, pub osd_op_log_threshold: String, pub osd_verify_sparse_read_holes: String, pub osd_debug_drop_ping_probability: String, pub osd_debug_drop_ping_duration: String, pub osd_debug_drop_pg_create_probability: String, pub osd_debug_drop_pg_create_duration: String, pub osd_debug_drop_op_probability: String, pub osd_debug_op_order: String, pub osd_debug_verify_snaps_on_info: String, pub osd_debug_verify_stray_on_activate: String, pub osd_debug_skip_full_check_in_backfill_reservation: String, pub osd_debug_reject_backfill_probability: String, pub osd_enable_op_tracker: String, } #[test] fn main() {} derivative-2.2.0/tests/rustc-issue-29710.rs010064400362620024044000000013561400305350200165600ustar0000000000000000// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![deny(unused_results)] #![allow(dead_code)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug)] struct A(usize); #[derive(Derivative)] #[derivative(Debug)] struct B { a: usize } #[test] fn main() {} derivative-2.2.0/tests/rustc-issue-32292.rs010064400362620024044000000013311400305350200165500ustar0000000000000000// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![deny(warnings)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Hash, Eq, PartialEq, Debug, Clone, Copy)] // TODO: Ord, PartialOrd struct Foo; #[test] fn main() { let _ = Foo; } derivative-2.2.0/tests/rustc-issue-3935.rs010064400362620024044000000014471400305350200165020ustar0000000000000000// Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(PartialEq)] struct Bike { name: String, } #[test] fn main() { let town_bike = Bike { name: "schwinn".to_string() }; let my_bike = Bike { name: "surly".to_string() }; assert!(town_bike != my_bike); } derivative-2.2.0/tests/rustc-issue-42453.rs010064400362620024044000000013001400305350200165440ustar0000000000000000// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![deny(warnings)] #![allow(dead_code)] #![allow(non_camel_case_types)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(Debug)] struct builder; fn main() { } derivative-2.2.0/tests/rustc-issue-58319.rs010064400362620024044000000176561400305350200166010ustar0000000000000000// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![deny(warnings)] #![allow(dead_code)] #![allow(non_camel_case_types)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; fn main() {} #[derive(Derivative)] #[derivative(Clone)] pub struct Little; #[derive(Clone)] pub struct Big( Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, Little, ); derivative-2.2.0/tests/rustc-issue-6341.rs010064400362620024044000000013501400305350200164650ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // pretty-expanded FIXME #23616 #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; #[derive(Derivative)] #[derivative(PartialEq)] struct A { x: usize } impl Drop for A { fn drop(&mut self) {} } #[test] fn main() { A { x: 42 }; } derivative-2.2.0/tests/rustc-typeclasses-eq-example.rs010064400362620024044000000045301400305350200213400ustar0000000000000000// Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(non_snake_case)] #![allow(non_camel_case_types)] #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; // Example from lkuper's intern talk, August 2012. use Color::{cyan, magenta, yellow, black}; use ColorTree::{leaf, branch}; trait Equal { fn isEq(&self, a: &Self) -> bool; } #[derive(Derivative)] #[derivative(Clone, Copy)] enum Color { cyan, magenta, yellow, black } impl Equal for Color { fn isEq(&self, a: &Color) -> bool { match (*self, *a) { (cyan, cyan) => { true } (magenta, magenta) => { true } (yellow, yellow) => { true } (black, black) => { true } _ => { false } } } } #[derive(Derivative)] #[derivative(Clone)] enum ColorTree { leaf(Color), branch(Box, Box) } impl Equal for ColorTree { fn isEq(&self, a: &ColorTree) -> bool { match (self, a) { (&leaf(ref x), &leaf(ref y)) => { x.isEq(&(*y)) } (&branch(ref l1, ref r1), &branch(ref l2, ref r2)) => { (*l1).isEq(&(**l2).clone()) && (*r1).isEq(&(**r2).clone()) } _ => { false } } } } #[test] fn main() { assert!(cyan.isEq(&cyan)); assert!(magenta.isEq(&magenta)); assert!(!cyan.isEq(&yellow)); assert!(!magenta.isEq(&cyan)); assert!(leaf(cyan).isEq(&leaf(cyan))); assert!(!leaf(cyan).isEq(&leaf(yellow))); assert!(branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))) .isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))))); assert!(branch(Box::new(leaf(black)), Box::new(leaf(cyan))) .isEq(&branch(Box::new(leaf(black)), Box::new(leaf(cyan))))); assert!(!branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))) .isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(magenta))))); println!("Assertions all succeeded!"); } derivative-2.2.0/tests/rustc-zero-sized-btreemap-insert.rs010064400362620024044000000022421400305350200221350ustar0000000000000000// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "use_core")] extern crate core; #[macro_use] extern crate derivative; use std::collections::BTreeMap; use std::iter::Iterator; #[derive(Derivative)] #[derive(Ord, PartialOrd)] #[derivative(Eq, Hash, Debug, PartialEq)] // TODO: Ord, PartialOrd struct Zst; #[test] fn main() { const N: usize = 8; for len in 0..N { let mut tester = BTreeMap::new(); assert_eq!(tester.len(), 0); for _ in 0..len { tester.insert(Zst, ()); } assert_eq!(tester.len(), if len == 0 { 0 } else { 1 }); assert_eq!(tester.iter().count(), if len == 0 { 0 } else { 1 }); assert_eq!(tester.get(&Zst).is_some(), len > 0); tester.clear(); } } derivative-2.2.0/.cargo_vcs_info.json0000644000000001120000000000000132300ustar00{ "git": { "sha1": "770c67484a872470ca782202e13fc70a35e2695b" } }