pax_global_header00006660000000000000000000000064147413303500014512gustar00rootroot0000000000000052 comment=6240530890c0066d7d3e6e5ef87810d565230142 auto_impl-1.2.1/000077500000000000000000000000001474133035000135045ustar00rootroot00000000000000auto_impl-1.2.1/.github/000077500000000000000000000000001474133035000150445ustar00rootroot00000000000000auto_impl-1.2.1/.github/workflows/000077500000000000000000000000001474133035000171015ustar00rootroot00000000000000auto_impl-1.2.1/.github/workflows/ci.yml000066400000000000000000000011111474133035000202110ustar00rootroot00000000000000name: CI on: [pull_request, push] env: CARGO_TERM_COLOR: always RUSTFLAGS: --deny warnings jobs: check: name: 'Build & test' runs-on: ubuntu-20.04 strategy: matrix: rust-version: ['stable', 'beta', 'nightly', '1.56'] steps: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@master with: toolchain: stable components: rustfmt, clippy - uses: Swatinem/rust-cache@v1 - run: cargo fmt --all -- --check - run: cargo clippy --workspace --all-features -- -D warnings - run: cargo test --workspace auto_impl-1.2.1/.gitignore000066400000000000000000000000371474133035000154740ustar00rootroot00000000000000/target/ **/*.rs.bk Cargo.lock auto_impl-1.2.1/Cargo.toml000066400000000000000000000014571474133035000154430ustar00rootroot00000000000000[package] name = "auto_impl" version = "1.2.1" authors = [ "Ashley Mannix ", "Lukas Kalbertodt ", ] license = "MIT OR Apache-2.0" description = "Automatically implement traits for common smart pointers and closures" repository = "https://github.com/auto-impl-rs/auto_impl/" documentation = "https://docs.rs/auto_impl/" keywords = ["trait", "impl", "proc-macro", "closure"] categories = ["development-tools", "rust-patterns"] readme = "README.md" autotests = true edition = "2021" rust-version = "1.56" [workspace] members = [ "examples/async_await" ] [lib] proc-macro = true [dependencies] proc-macro2 = "1.0" quote = "1.0" syn = { version = "2.0", features = ["full", "visit", "visit-mut"] } [dev-dependencies] trybuild = "1" rustversion = "1" auto_impl-1.2.1/LICENSE-APACHE000066400000000000000000000251421474133035000154340ustar00rootroot00000000000000 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. auto_impl-1.2.1/LICENSE-MIT000066400000000000000000000020501474133035000151350ustar00rootroot00000000000000Copyright (c) 2018 auto_impl Developers 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. auto_impl-1.2.1/README.md000066400000000000000000000045051474133035000147670ustar00rootroot00000000000000# `auto_impl` [![CI](https://github.com/auto-impl-rs/auto_impl/actions/workflows/ci.yml/badge.svg)](https://github.com/auto-impl-rs/auto_impl/actions/workflows/ci.yml) [![Crates.io](https://img.shields.io/crates/v/auto_impl.svg)](https://crates.io/crates/auto_impl) [![docs](https://docs.rs/auto_impl/badge.svg)](https://docs.rs/auto_impl) A proc-macro attribute for automatically implementing a trait for references, some common smart pointers and closures. # Usage This library requires Rust 1.56.0 or newer. This library doesn't leave any public API in your code. Add `auto_impl` to your `Cargo.toml` and just use it in your crate: ```rust // In Rust 2015 you still need `extern crate auto_impl;` at your crate root use auto_impl::auto_impl; ``` Add an `auto_impl` attribute to traits you want to automatically implement for wrapper types. Here is a small example: ```rust // This will generate two additional impl blocks: one for `&T` and one // for `Box` where `T: Foo`. #[auto_impl(&, Box)] trait Foo { fn foo(&self); } impl Foo for i32 { fn foo(&self) {} } fn requires_foo(_: impl Foo) {} requires_foo(0i32); // works: through the impl we defined above requires_foo(&0i32); // works: through the generated impl requires_foo(Box::new(0i32)); // works: through the generated impl ``` For more explanations, please see [**the documentation**](https://docs.rs/auto_impl) and for more examples, see [the examples folder](https://github.com/auto-impl-rs/auto_impl/tree/master/examples). # Alternatives This library implements a fraction of a very broad and complex usecase. It's mostly useful for applications that define traits for components, and want to be able to abstract over the storage for those traits. If it doesn't offer some functionality you need, check out the [`impl-tools`](https://github.com/kas-gui/impl-tools/) project. --- ## License Licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### 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. auto_impl-1.2.1/examples/000077500000000000000000000000001474133035000153225ustar00rootroot00000000000000auto_impl-1.2.1/examples/README.md000066400000000000000000000011261474133035000166010ustar00rootroot00000000000000# Examples - `error_messages`: contains some incorrect code that showcases the error messages emitted by `auto_impl` - **`greet_closure`**: simple example showing how to auto impl for `Fn` traits - **`keep_default_for`**: shows how to use the `#[auto_impl(keep_default_for(...))]` attribute - `names`: showcases how `auto_impl` chooses new ident names - **`refs`**: shows how to auto impl for `&` and `Box` **Note**: if you want to see what the generated impl blocks look like, use the execellent [`cargo expand`](https://github.com/dtolnay/cargo-expand): ``` $ cargo expand --example refs ``` auto_impl-1.2.1/examples/async_await/000077500000000000000000000000001474133035000176245ustar00rootroot00000000000000auto_impl-1.2.1/examples/async_await/Cargo.toml000066400000000000000000000003771474133035000215630ustar00rootroot00000000000000[package] name = "auto_impl_async_await_example" version = "0.0.0" publish = false edition = "2021" license = "MIT OR Apache-2.0" [dependencies] auto_impl = { path = "../../" } async-trait = "0.1" async-std = { version = "1", features = ["attributes"] } auto_impl-1.2.1/examples/async_await/src/000077500000000000000000000000001474133035000204135ustar00rootroot00000000000000auto_impl-1.2.1/examples/async_await/src/main.rs000066400000000000000000000012141474133035000217030ustar00rootroot00000000000000use async_std::task; use std::time::Duration; use async_trait::async_trait; use auto_impl::auto_impl; // Note the order of the attributes here: // `#[async_trait]` must appear first #[async_trait] #[auto_impl(&, Box, Arc)] trait Component { async fn run(&self); } struct WaitABit(Duration); #[async_trait] impl Component for WaitABit { async fn run(&self) { task::sleep(self.0).await; } } async fn run_async(a: impl Component) { a.run().await; } #[async_std::main] async fn main() { // We can treat our `Box` as an `impl Component` directly run_async(Box::new(WaitABit(Duration::from_secs(1)))).await; } auto_impl-1.2.1/examples/error_messages.rs000066400000000000000000000013521474133035000207110ustar00rootroot00000000000000//! This file showcases a few error messages emitted by `auto_impl`. You have //! to add specific lines to see the error. Then simply compile with: //! //! ``` //! cargo build --example error_messages //! ``` #![allow(unused_imports, dead_code)] use auto_impl::auto_impl; // Shows the error message for the case that `#[auto_impl]` was used with // incorrect proxy types. Only proxy types like `&` and `Box` are allowed. Add // this next line to see the error! //#[auto_impl(Boxxi)] trait Foo { fn foo(&self) -> u32; } // Shows the error message for the case the `#[auto_impl]` wasn't applied to a // valid trait (in this case a struct). Add this next line to see the error! //#[auto_impl(&, Box)] struct Bar { x: u32, } fn main() {} auto_impl-1.2.1/examples/greet_closure.rs000066400000000000000000000021351474133035000205330ustar00rootroot00000000000000use auto_impl::auto_impl; /// This simple trait can be implemented for `Fn` types, but not for `FnMut` or /// `FnOnce` types. The latter two types require a mutable reference to `self` /// or a `self` by value to be called, but `greet()` only has an immutable /// reference. Try creating an auto-impl for `FnMut`: you should get an error. /// /// This attribute expands to the following impl (not exactly this code, but /// equivalent, slightly uglier code): /// /// ``` /// impl Greeter for F { /// fn greet(&self, name: &str) { /// self(name) /// } /// } /// ``` #[auto_impl(Fn)] trait Greeter { fn greet(&self, name: &str); } fn greet_people(greeter: impl Greeter) { greeter.greet("Anna"); greeter.greet("Bob"); } fn main() { // We can simply pass a closure here, since this specific closure // implements `Fn(&str)` and therefore also `Greeter`. Note that we need // explicit type annotations here. This has nothing to do with `auto_impl`, // but is simply a limitation of type inference. greet_people(|name: &str| println!("Hallo {} :)", name)); } auto_impl-1.2.1/examples/keep_default_for.rs000066400000000000000000000025011474133035000211640ustar00rootroot00000000000000//! Example to demonstrate how to use the `keep_default_for` attribute. //! //! The generated `impl` blocks generate an item for each trait item by //! default. This means that default methods in traits are also implemented via //! the proxy type. Sometimes, this is not what you want. One special case is //! when the default method has where bounds that don't apply to the proxy //! type. use auto_impl::auto_impl; #[auto_impl(&, Box)] trait Foo { fn required(&self) -> String; // The generated impl for `&T` will not override this method. #[auto_impl(keep_default_for(&))] fn provided(&self) { println!("Hello {}", self.required()); } } impl Foo for String { fn required(&self) -> String { self.clone() } fn provided(&self) { println!("привет {}", self); } } fn test_foo(x: impl Foo) { x.provided(); } fn main() { let s = String::from("Peter"); // Output: "привет Peter", because `String` has overwritten the default // method. test_foo(s.clone()); // Output: "Hello Peter", because the method is not overwritten for the // `&T` impl block. test_foo(&s); // Output: "привет Peter", because the `Box` impl overwrites the method // by default, if you don't specify `keep_default_for`. test_foo(Box::new(s)); } auto_impl-1.2.1/examples/names.rs000066400000000000000000000031261474133035000167750ustar00rootroot00000000000000//! Example to demonstrate how `auto_impl` chooses a name for the type and //! lifetime parameter. //! //! For documentation and compiler errors it would be nice to have very simple //! names for type and lifetime parameters: //! //! ```rust //! // not nice //! impl<'auto_impl_lifetime, AutoImplT> Foo for &'auto_impl_lifetime AutoImplT { ...} //! //! // better //! impl<'a, T> Foo for &'a T { ... } //! ``` //! //! `auto_impl` tries the full alphabet, picking a name that is not yet taken. //! "Not taken" means that the name is not used anywhere in the `impl` block. //! Right now, we are a bit careful and mark all names as "taken" that are used //! in the trait def -- apart from names only appearing in the body of provided //! methods. //! //! In the trait below, a bunch of names are already "taken": //! - type names: T--Z and A--G (H is not taken, because it only appear in the //! default method body) //! - lifetime names: 'a--'c //! //! Thus, the names `H` and `'d` are used. Run `cargo expand --example names` //! to see the output. // This code is really ugly on purpose... #![allow(non_snake_case, dead_code, unused_variables, clippy::extra_unused_lifetimes, clippy::let_unit_value, clippy::redundant_allocation)] #![cfg_attr(rustfmt, rustfmt::skip)] use auto_impl::auto_impl; struct X {} trait Z {} struct C {} struct E(Vec); struct F {} struct G(Vec); struct H {} #[auto_impl(&)] trait U<'a, V> { const W: Option>; type Y: Z; fn A<'b, 'c>(&self, B: C, D: E<&[F; 1]>) -> G { let H = (); unimplemented!() } } fn main() {} auto_impl-1.2.1/examples/refs.rs000066400000000000000000000033451474133035000166340ustar00rootroot00000000000000use std::fmt::Display; use auto_impl::auto_impl; /// This trait can be implemented for all reference or pointer types: &, &mut, /// Box, Rc and Arc. /// /// This attribute expands to the following impl (not exactly this code, but /// equivalent, slightly uglier code): /// /// ``` /// impl<'a, T: 'a + DisplayCollection> DisplayCollection for &'a T { /// type Out = T::Out; /// fn display_at(&self, index: usize) -> Option<&Self::Out> { /// (**self).display_at(index) /// } /// } /// /// impl DisplayCollection for Box { /// type Out = T::Out; /// fn display_at(&self, index: usize) -> Option<&Self::Out> { /// (**self).display_at(index) /// } /// } /// ``` #[auto_impl(&, Box)] trait DisplayCollection { /// If the length is statically known, this is `Some(len)`. const LEN: Option; type Out: Display; fn display_at(&self, index: usize) -> Option<&Self::Out>; } impl DisplayCollection for Vec { type Out = T; const LEN: Option = None; fn display_at(&self, index: usize) -> Option<&Self::Out> { self.get(index) } } fn show_first(c: impl DisplayCollection) { match c.display_at(0) { Some(x) => println!("First: {}", x), None => println!("Nothing :/"), } } #[allow(clippy::needless_borrow)] #[rustfmt::skip] fn main() { let v = vec!["dog", "cat"]; let boxed = Box::new(v.clone()); show_first(v.clone()); // Vec<&str> (our manual impl) show_first(&v); // &Vec<&str> (auto-impl) show_first(&&v); // &&Vec<&str> (works too, of course) show_first(boxed.clone()); // Box> (auto-impl) show_first(&boxed); // &Box> } auto_impl-1.2.1/rustfmt.toml000066400000000000000000000002431474133035000161040ustar00rootroot00000000000000unstable_features = true blank_lines_upper_bound = 3 format_macro_matchers = true imports_granularity="Crate" normalize_comments = true reorder_impl_items = true auto_impl-1.2.1/src/000077500000000000000000000000001474133035000142735ustar00rootroot00000000000000auto_impl-1.2.1/src/analyze.rs000066400000000000000000000070501474133035000163060ustar00rootroot00000000000000use std::collections::HashSet; use proc_macro2::Span as Span2; use syn::{ visit::{visit_item_trait, Visit}, Block, Ident, ItemTrait, Lifetime, }; /// The type parameter used in the proxy type. Usually, one would just use `T`, /// but this could conflict with type parameters on the trait. /// /// Why do we have to care about this? Why about hygiene? In the first version /// of stable proc_macros, only call site spans are included. That means that /// we cannot generate spans that do not conflict with any other ident the user /// wrote. Once proper hygiene is available to proc_macros, this should be /// changed. const PROXY_TY_PARAM_NAME: &str = "__AutoImplProxyT"; /// The lifetime parameter used in the proxy type if the proxy type is `&` or /// `&mut`. For more information see `PROXY_TY_PARAM_NAME`. const PROXY_LT_PARAM_NAME: &str = "'__auto_impl_proxy_lifetime"; /// We need to introduce our own type and lifetime parameter. Regardless of /// what kind of hygiene we use for the parameter, it would be nice (for docs /// and compiler errors) if the names are as simple as possible ('a and T, for /// example). /// /// This function searches for names that we can use. Such a name must not /// conflict with any other name we'll use in the `impl` block. Luckily, we /// know all those names in advance. /// /// The idea is to collect all names that might conflict with our names, store /// them in a set and later check which name we can use. If we can't use a simple /// name, we'll use the ugly `PROXY_TY_PARAM_NAME` and `PROXY_LT_PARAM_NAME`. /// /// This method returns two idents: (type_parameter, lifetime_parameter). pub(crate) fn find_suitable_param_names(trait_def: &ItemTrait) -> (Ident, Lifetime) { // Define the visitor that just collects names struct IdentCollector<'ast> { ty_names: HashSet<&'ast Ident>, lt_names: HashSet<&'ast Ident>, } impl<'ast> Visit<'ast> for IdentCollector<'ast> { fn visit_ident(&mut self, i: &'ast Ident) { self.ty_names.insert(i); } // We overwrite this to make sure to put lifetime names into // `lt_names`. We also don't recurse, so `visit_ident` won't be called // for lifetime names. fn visit_lifetime(&mut self, lt: &'ast Lifetime) { self.lt_names.insert(<.ident); } // Visiting a block just does nothing. It is the default body of a method // in the trait. But since that block won't be in the impl block, we can // just ignore it. fn visit_block(&mut self, _: &'ast Block) {} } // Create the visitor and visit the trait let mut visitor = IdentCollector { ty_names: HashSet::new(), lt_names: HashSet::new(), }; visit_item_trait(&mut visitor, trait_def); fn char_to_ident(c: u8) -> Ident { let arr = [c]; let s = ::std::str::from_utf8(&arr).unwrap(); Ident::new(s, param_span()) } // Find suitable type name (T..=Z and A..=S) let ty_name = (b'T'..=b'Z') .chain(b'A'..=b'S') .map(char_to_ident) .find(|i| !visitor.ty_names.contains(i)) .unwrap_or_else(|| Ident::new(PROXY_TY_PARAM_NAME, param_span())); // Find suitable lifetime name ('a..='z) let lt_name = (b'a'..=b'z') .map(char_to_ident) .find(|i| !visitor.lt_names.contains(i)) .unwrap_or_else(|| Ident::new(PROXY_LT_PARAM_NAME, param_span())); let lt = Lifetime { apostrophe: param_span(), ident: lt_name, }; (ty_name, lt) } fn param_span() -> Span2 { Span2::call_site() } auto_impl-1.2.1/src/attr.rs000066400000000000000000000116761474133035000156260ustar00rootroot00000000000000//! Internal attributes of the form `#[auto_impl(name(...))]` that can be //! attached to trait items. use proc_macro2::{Delimiter, TokenTree}; use syn::{ spanned::Spanned, visit_mut::{visit_item_trait_mut, VisitMut}, Attribute, Error, Meta, TraitItem, }; use crate::proxy::{parse_types, ProxyType}; /// Removes all `#[auto_impl]` attributes that are attached to methods of the /// given trait. pub(crate) fn remove_our_attrs(trait_def: &mut syn::ItemTrait) -> syn::Result<()> { struct AttrRemover(syn::Result<()>); impl VisitMut for AttrRemover { fn visit_trait_item_mut(&mut self, item: &mut TraitItem) { let item_span = item.span(); let (attrs, is_method) = match item { TraitItem::Fn(m) => (&mut m.attrs, true), TraitItem::Const(c) => (&mut c.attrs, false), TraitItem::Type(t) => (&mut t.attrs, false), TraitItem::Macro(m) => (&mut m.attrs, false), _ => { let err = syn::Error::new( item.span(), "encountered unexpected `TraitItem`, cannot handle that, sorry!", ); if let Err(ref mut current_err) = self.0 { current_err.combine(err); } else { self.0 = Err(err); }; return; } }; // Make sure non-methods do not have our attributes. if !is_method && attrs.iter().any(is_our_attr) { let err = syn::Error::new( item_span, "`#[auto_impl]` attributes are only allowed on methods", ); if let Err(ref mut current_err) = self.0 { current_err.combine(err); } else { self.0 = Err(err); }; return; } attrs.retain(|a| !is_our_attr(a)); } } let mut visitor = AttrRemover(Ok(())); visit_item_trait_mut(&mut visitor, trait_def); visitor.0 } /// Checks if the given attribute is "our" attribute. That means that it's path /// is `auto_impl`. pub(crate) fn is_our_attr(attr: &Attribute) -> bool { attr.path().is_ident("auto_impl") } /// Tries to parse the given attribute as one of our own `auto_impl` /// attributes. If it's invalid, an error is emitted and `Err(())` is returned. /// You have to make sure that `attr` is one of our attrs with `is_our_attr` /// before calling this function! pub(crate) fn parse_our_attr(attr: &Attribute) -> syn::Result { assert!(is_our_attr(attr)); // Get the body of the attribute (which has to be a ground, because we // required the syntax `auto_impl(...)` and forbid stuff like // `auto_impl = ...`). let body = match &attr.meta { Meta::List(list) => list.tokens.clone(), _ => { return Err(Error::new( attr.span(), "expected single group delimited by `()`", )); } }; let mut it = body.clone().into_iter(); // Try to extract the name (we require the body to be `name(...)`). let name = match it.next() { Some(TokenTree::Ident(x)) => x, Some(other) => { return Err(Error::new( other.span(), format_args!("expected ident, found '{}'", other), )); } None => { return Err(Error::new(attr.span(), "expected ident, found nothing")); } }; // Extract the parameters (which again, have to be a group delimited by // `()`) let params = match it.next() { Some(TokenTree::Group(ref g)) if g.delimiter() == Delimiter::Parenthesis => g.stream(), Some(other) => { return Err(Error::new( other.span(), format_args!( "expected arguments for '{}' in parenthesis `()`, found `{}`", name, other ), )); } None => { return Err(Error::new( body.span(), format_args!( "expected arguments for '{}' in parenthesis `()`, found nothing", name, ), )); } }; // Finally match over the name of the attribute. let out = if name == "keep_default_for" { let proxy_types = parse_types(params.into()); OurAttr::KeepDefaultFor(proxy_types) } else { return Err(Error::new( name.span(), format_args!( "invalid attribute '{}'; only `keep_default_for` is supported", name ), )); }; Ok(out) } /// Attributes of the form `#[auto_impl(...)]` that can be attached to items of /// the trait. #[derive(Clone, PartialEq, Debug)] pub(crate) enum OurAttr { KeepDefaultFor(Vec), } auto_impl-1.2.1/src/gen.rs000066400000000000000000001041671474133035000154230ustar00rootroot00000000000000use proc_macro2::{Span as Span2, TokenStream as TokenStream2, TokenTree as TokenTree2}; use quote::{ToTokens, TokenStreamExt}; use syn::{ punctuated::Punctuated, spanned::Spanned, Attribute, Error, FnArg, GenericParam, Ident, ItemTrait, Lifetime, Pat, PatIdent, PatType, ReturnType, Signature, Token, TraitBound, TraitBoundModifier, TraitItem, TraitItemConst, TraitItemFn, TraitItemType, Type, TypeParamBound, WherePredicate, }; use crate::{ analyze::find_suitable_param_names, attr::{is_our_attr, parse_our_attr, OurAttr}, proxy::ProxyType, }; /// Generates one complete impl of the given trait for each of the given proxy /// types. All impls are returned as token stream. pub(crate) fn gen_impls( proxy_types: &[ProxyType], trait_def: &syn::ItemTrait, ) -> syn::Result { let mut tokens = TokenStream2::new(); let (proxy_ty_param, proxy_lt_param) = find_suitable_param_names(trait_def); // One impl for each proxy type for proxy_type in proxy_types { let header = gen_header(proxy_type, trait_def, &proxy_ty_param, &proxy_lt_param)?; let items = gen_items(proxy_type, trait_def, &proxy_ty_param)?; if let ProxyType::Box | ProxyType::Rc | ProxyType::Arc = proxy_type { tokens.append_all(quote! { const _: () = { extern crate alloc; #header { #( #items )* } }; }); } else { tokens.append_all(quote! { const _: () = { #header { #( #items )* } }; }); } } Ok(tokens) } /// Generates the header of the impl of the given trait for the given proxy /// type. fn gen_header( proxy_type: &ProxyType, trait_def: &ItemTrait, proxy_ty_param: &Ident, proxy_lt_param: &Lifetime, ) -> syn::Result { // Generate generics for impl positions from trait generics. let (impl_generics, trait_generics, where_clause) = trait_def.generics.split_for_impl(); // The name of the trait with all generic parameters applied. let trait_ident = &trait_def.ident; let trait_path = quote! { #trait_ident #trait_generics }; // Here we assemble the parameter list of the impl (the thing in // `impl< ... >`). This is simply the parameter list of the trait with // one or two parameters added. For a trait `trait Foo<'x, 'y, A, B>`, // it will look like this: // // '{proxy_lt_param}, 'x, 'y, A, B, {proxy_ty_param} // // The `'{proxy_lt_param}` in the beginning is only added when the proxy // type is `&` or `&mut`. let impl_generics = { // Determine whether we can add a `?Sized` relaxation to allow trait // objects. We can do that as long as there is no method that has a // `self` by value receiver and no `where Self: Sized` bound. let methods = trait_def .items .iter() // Only interested in methods .filter_map(|item| { if let TraitItem::Fn(m) = item { Some(m) } else { None } }); let mut sized_required = false; for m in methods { if should_keep_default_for(m, proxy_type)? { continue; } // Check if there is a `Self: Sized` bound on the method. let self_is_bounded_sized = m .sig .generics .where_clause .iter() .flat_map(|wc| &wc.predicates) .filter_map(|pred| { if let WherePredicate::Type(p) = pred { Some(p) } else { None } }) .any(|pred| { // Check if the type is `Self` match &pred.bounded_ty { Type::Path(p) if p.path.is_ident("Self") => { // Check if the bound contains `Sized` pred.bounds.iter().any(|b| match b { TypeParamBound::Trait(TraitBound { modifier: TraitBoundModifier::None, path, .. }) => path.is_ident("Sized"), _ => false, }) } _ => false, } }); // Check if the first parameter is `self` by value. In that // case, we might require `Self` to be `Sized`. let self_value_param = match m.sig.inputs.first() { Some(FnArg::Receiver(receiver)) => receiver.reference.is_none(), _ => false, }; // Check if return type is `Self` let self_value_return = match &m.sig.output { ReturnType::Type(_, t) => { if let Type::Path(p) = &**t { p.path.is_ident("Self") } else { false } } _ => false, }; // TODO: check for `Self` parameter in any other argument. // If for this method, `Self` is used in a position that // requires `Self: Sized` or this bound is added explicitly, we // cannot add the `?Sized` relaxation to the impl body. if self_value_param || self_value_return || self_is_bounded_sized { sized_required = true; break; } } let relaxation = if sized_required { quote! {} } else { quote! { + ?::core::marker::Sized } }; // Check if there are some `Self: Foo` bounds on methods. If so, we // need to add those bounds to `T` as well. See issue #11 for more // information, but in short: there is no better solution. Method where // clauses with `Self: Foo` force us to add `T: Foo` to the impl // header, as we otherwise cannot generate a valid impl block. let methods = trait_def .items .iter() // Only interested in methods .filter_map(|item| { if let TraitItem::Fn(m) = item { Some(m) } else { None } }); let mut additional_bounds = Vec::new(); for m in methods { if should_keep_default_for(m, proxy_type)? { continue; } additional_bounds.extend( m.sig .generics .where_clause .iter() .flat_map(|wc| &wc.predicates) .filter_map(|pred| { if let WherePredicate::Type(p) = pred { Some(p) } else { None } }) .filter(|p| { // Only `Self:` bounds match &p.bounded_ty { Type::Path(p) => p.path.is_ident("Self"), _ => false, } }) .flat_map(|p| &p.bounds) .filter_map(|b| { // We are only interested in trait bounds. That's // because lifetime bounds on `Self` do not need to be // added to the impl header. That's because all values // "derived" from `self` also meet the same lifetime // bound as `self`. In simpler terms: while `self.field` // might not be `Clone` even if `Self: Clone`, // `self.field` is always `: 'a` if `Self: 'a`. match b { TypeParamBound::Trait(t) => Some(t), _ => None, } }), ); } // Determine if our proxy type needs a lifetime parameter let (mut params, ty_bounds) = match proxy_type { ProxyType::Ref | ProxyType::RefMut => ( quote! { #proxy_lt_param, }, quote! { : #proxy_lt_param + #trait_path #relaxation #(+ #additional_bounds)* }, ), ProxyType::Box | ProxyType::Rc | ProxyType::Arc => ( quote! {}, quote! { : #trait_path #relaxation #(+ #additional_bounds)* }, ), ProxyType::Fn | ProxyType::FnMut | ProxyType::FnOnce => { let fn_bound = gen_fn_type_for_trait(proxy_type, trait_def)?; (quote! {}, quote! { : #fn_bound }) } }; // Append all parameters from the trait. Sadly, `impl_generics` // includes the angle brackets `< >` so we have to remove them like // this. let mut tts = impl_generics .into_token_stream() .into_iter() .skip(1) // the opening `<` .collect::>(); tts.pop(); // the closing `>` // Pop a trailing comma if there is one // We'll end up conditionally putting one back in shortly if tts.last().and_then(|tt| { if let TokenTree2::Punct(p) = tt { Some(p.as_char()) } else { None } }) == Some(',') { tts.pop(); } params.append_all(&tts); // Append proxy type parameter (if there aren't any parameters so far, // we need to add a comma first). let comma = if params.is_empty() || tts.is_empty() { quote! {} } else { quote! { , } }; params.append_all(quote! { #comma #proxy_ty_param #ty_bounds }); params }; // The tokens after `for` in the impl header (the type the trait is // implemented for). #[rustfmt::skip] let self_ty = match *proxy_type { ProxyType::Ref => quote! { & #proxy_lt_param #proxy_ty_param }, ProxyType::RefMut => quote! { & #proxy_lt_param mut #proxy_ty_param }, ProxyType::Arc => quote! { alloc::sync::Arc<#proxy_ty_param> }, ProxyType::Rc => quote! { alloc::rc::Rc<#proxy_ty_param> }, ProxyType::Box => quote! { alloc::boxed::Box<#proxy_ty_param> }, ProxyType::Fn => quote! { #proxy_ty_param }, ProxyType::FnMut => quote! { #proxy_ty_param }, ProxyType::FnOnce => quote! { #proxy_ty_param }, }; // If the trait has super traits, we need to add the super trait bound to // our self type. This can only be done in the where clause, so we need to // combine the existing where clauses with our new predicate in that case. let where_clause = if !trait_def.supertraits.is_empty() { let mut out = quote! { where }; if !trait_def.supertraits.is_empty() { let supertraits = &trait_def.supertraits; out.extend(quote! { #self_ty: #supertraits, }); } if let Some(predicates) = where_clause.map(|c| &c.predicates) { out.extend(predicates.into_token_stream()); } out } else { where_clause.into_token_stream() }; // Combine everything Ok(quote! { impl<#impl_generics> #trait_path for #self_ty #where_clause }) } /// Generates the Fn-trait type (e.g. `FnMut(u32) -> String`) for the given /// trait and proxy type (the latter has to be `Fn`, `FnMut` or `FnOnce`!) /// /// If the trait is unsuitable to be implemented for the given proxy type, an /// error is emitted. fn gen_fn_type_for_trait( proxy_type: &ProxyType, trait_def: &ItemTrait, ) -> syn::Result { // Only traits with exactly one method can be implemented for Fn-traits. // Associated types and consts are also not allowed. let method = trait_def.items.first().and_then(|item| { if let TraitItem::Fn(m) = item { Some(m) } else { None } }); // If this requirement is not satisfied, we emit an error. if method.is_none() || trait_def.items.len() > 1 { return Err(Error::new( trait_def.span(), "this trait cannot be auto-implemented for Fn-traits (only traits with exactly \ one method and no other items are allowed)", )); } // We checked for `None` above let method = method.unwrap(); let sig = &method.sig; // Check for forbidden modifier of the method if let Some(const_token) = sig.constness { return Err(Error::new( const_token.span(), format_args!( "the trait '{}' cannot be auto-implemented for Fn-traits: const methods are not \ allowed", trait_def.ident ), )); } if let Some(unsafe_token) = &sig.unsafety { return Err(Error::new( unsafe_token.span(), format_args!( "the trait '{}' cannot be auto-implemented for Fn-traits: unsafe methods are not \ allowed", trait_def.ident ), )); } if let Some(abi_token) = &sig.abi { return Err(Error::new( abi_token.span(), format_args!( "the trait '{}' cannot be implemented for Fn-traits: custom ABIs are not allowed", trait_def.ident ), )); } // Function traits cannot support generics in their arguments // These would require HRTB for types instead of just lifetimes let mut r: syn::Result<()> = Ok(()); for type_param in sig.generics.type_params() { let err = Error::new( type_param.span(), format_args!("the trait '{}' cannot be implemented for Fn-traits: generic arguments are not allowed", trait_def.ident), ); if let Err(ref mut current_err) = r { current_err.combine(err); } else { r = Err(err); } } for const_param in sig.generics.const_params() { let err = Error::new( const_param.span(), format_args!("the trait '{}' cannot be implemented for Fn-traits: constant arguments are not allowed", trait_def.ident), ); if let Err(ref mut current_err) = r { current_err.combine(err); } else { r = Err(err); } } r?; // ======================================================================= // Check if the trait can be implemented for the given proxy type let self_type = SelfType::from_sig(sig); let err = match (self_type, proxy_type) { // The method needs to have a receiver (SelfType::None, _) => Some(("Fn-traits", "no", "")), // We can't impl methods with `&mut self` or `&self` receiver for // `FnOnce` (SelfType::Mut, ProxyType::FnOnce) => { Some(("`FnOnce`", "a `&mut self`", " (only `self` is allowed)")) } (SelfType::Ref, ProxyType::FnOnce) => { Some(("`FnOnce`", "a `&self`", " (only `self` is allowed)")) } // We can't impl methods with `&self` receiver for `FnMut` (SelfType::Ref, ProxyType::FnMut) => Some(( "`FnMut`", "a `&self`", " (only `self` and `&mut self` are allowed)", )), // Other combinations are fine _ => None, }; if let Some((fn_traits, receiver, allowed)) = err { return Err(Error::new( method.sig.span(), format_args!( "the trait '{}' cannot be auto-implemented for {}, because this method has \ {} receiver{}", trait_def.ident, fn_traits, receiver, allowed, ), )); } // ======================================================================= // Generate the full Fn-type // The path to the Fn-trait let fn_name = match proxy_type { ProxyType::Fn => quote! { ::core::ops::Fn }, ProxyType::FnMut => quote! { ::core::ops::FnMut }, ProxyType::FnOnce => quote! { ::core::ops::FnOnce }, _ => panic!("internal error in auto_impl (function contract violation)"), }; // The return type let ret = &sig.output; // Now it gets a bit complicated. The types of the function signature // could contain "local" lifetimes, meaning that they are not declared in // the trait definition (or are `'static`). We need to extract all local // lifetimes to declare them with HRTB (e.g. `for<'a>`). // // In Rust 2015 that was easy: we could just take the lifetimes explicitly // declared in the function signature. Those were the local lifetimes. // Unfortunately, with in-band lifetimes, things get more complicated. We // need to take a look at all lifetimes inside the types (arbitrarily deep) // and check if they are local or not. // // In cases where lifetimes are omitted (e.g. `&str`), we don't have a // problem. If we just translate that to `for<> Fn(&str)`, it's fine: all // omitted lifetimes in an `Fn()` type are automatically declared as HRTB. // // TODO: Implement this check for in-band lifetimes! let local_lifetimes = sig.generics.lifetimes(); // The input types as comma separated list. We skip the first argument, as // this is the receiver argument. let mut arg_types = TokenStream2::new(); for arg in sig.inputs.iter().skip(1) { match arg { FnArg::Typed(pat) => { let ty = &pat.ty; arg_types.append_all(quote! { #ty , }); } // We skipped the receiver already. FnArg::Receiver(r) => { return Err(Error::new( r.span(), "receiver argument that's not the first argument (auto_impl is confused)", )); } } } Ok(quote! { for< #(#local_lifetimes),* > #fn_name (#arg_types) #ret }) } /// Generates the implementation of all items of the given trait. These /// implementations together are the body of the `impl` block. fn gen_items( proxy_type: &ProxyType, trait_def: &ItemTrait, proxy_ty_param: &Ident, ) -> syn::Result> { trait_def .items .iter() .map(|item| { match item { TraitItem::Const(c) => gen_const_item(proxy_type, c, trait_def, proxy_ty_param), TraitItem::Fn(method) => { gen_method_item(proxy_type, method, trait_def, proxy_ty_param) } TraitItem::Type(ty) => gen_type_item(proxy_type, ty, trait_def, proxy_ty_param), TraitItem::Macro(mac) => { // We cannot resolve the macro invocation and thus cannot know // if it adds additional items to the trait. Thus, we have to // give up. Err(Error::new( mac.span(), "traits with macro invocations in their bodies are not \ supported by auto_impl", )) } TraitItem::Verbatim(v) => { // I don't quite know when this happens, but it's better to // notify the user with a nice error instead of panicking. Err(Error::new( v.span(), "unexpected 'verbatim'-item (auto-impl doesn't know how to handle it)", )) } _ => { // `syn` enums are `non_exhaustive` to be future-proof. If a // trait contains a kind of item we don't even know about, we // emit an error. Err(Error::new( item.span(), "unknown trait item (auto-impl doesn't know how to handle it)", )) } } }) .collect() } /// Generates the implementation of an associated const item described by /// `item`. The implementation is returned as token stream. /// /// If the proxy type is an Fn*-trait, an error is emitted and `Err(())` is /// returned. fn gen_const_item( proxy_type: &ProxyType, item: &TraitItemConst, trait_def: &ItemTrait, proxy_ty_param: &Ident, ) -> syn::Result { // A trait with associated consts cannot be implemented for Fn* types. if proxy_type.is_fn() { return Err(Error::new( item.span(), format_args!("the trait `{}` cannot be auto-implemented for Fn-traits, because it has \ associated consts (only traits with a single method can be implemented for Fn-traits)", trait_def.ident) )); } // We simply use the associated const from our type parameter. let const_name = &item.ident; let const_ty = &item.ty; let attrs = filter_attrs(&item.attrs); Ok(quote! { #(#attrs)* const #const_name: #const_ty = #proxy_ty_param::#const_name; }) } /// Generates the implementation of an associated type item described by `item`. /// The implementation is returned as token stream. /// /// If the proxy type is an Fn*-trait, an error is emitted and `Err(())` is /// returned. fn gen_type_item( proxy_type: &ProxyType, item: &TraitItemType, trait_def: &ItemTrait, proxy_ty_param: &Ident, ) -> syn::Result { // A trait with associated types cannot be implemented for Fn* types. if proxy_type.is_fn() { return Err(Error::new( item.span(), format_args!("the trait `{}` cannot be auto-implemented for Fn-traits, because it has \ associated types (only traits with a single method can be implemented for Fn-traits)", trait_def.ident) )); } // We simply use the associated type from our type parameter. let assoc_name = &item.ident; let attrs = filter_attrs(&item.attrs); let generics = &item.generics; Ok(quote! { #(#attrs)* type #assoc_name #generics = #proxy_ty_param::#assoc_name #generics; }) } /// Generates the implementation of a method item described by `item`. The /// implementation is returned as token stream. /// /// This function also performs sanity checks, e.g. whether the proxy type can /// be used to implement the method. If any error occurs, the error is /// immediately emitted and `Err(())` is returned. fn gen_method_item( proxy_type: &ProxyType, item: &TraitItemFn, trait_def: &ItemTrait, proxy_ty_param: &Ident, ) -> syn::Result { // If this method has a `#[auto_impl(keep_default_for(...))]` attribute for // the given proxy type, we don't generate anything for this impl block. if should_keep_default_for(item, proxy_type)? { return if item.default.is_some() { Ok(TokenStream2::new()) } else { Err(Error::new( item.sig.span(), format_args!( "the method `{}` has the attribute `keep_default_for` but is not a default \ method (no body is provided)", item.sig.ident ), )) }; } // Determine the kind of the method, determined by the self type. let sig = &item.sig; let self_arg = SelfType::from_sig(sig); let attrs = filter_attrs(&item.attrs); // Check self type and proxy type combination check_receiver_compatible(proxy_type, self_arg, &trait_def.ident, sig.span())?; // Generate the list of argument used to call the method. let (inputs, args) = get_arg_list(sig.inputs.iter())?; // Construct a signature we'll use to generate the proxy method impl // This is _almost_ the same as the original, except we use the inputs constructed // alongside the args. These may be slightly different than the original trait. let sig = Signature { constness: item.sig.constness, asyncness: item.sig.asyncness, unsafety: item.sig.unsafety, abi: item.sig.abi.clone(), fn_token: item.sig.fn_token, ident: item.sig.ident.clone(), generics: item.sig.generics.clone(), paren_token: item.sig.paren_token, inputs, variadic: item.sig.variadic.clone(), output: item.sig.output.clone(), }; // Build the turbofish type parameters. We need to pass type parameters // explicitly as they cannot be inferred in all cases (e.g. something like // `mem::size_of`). However, we don't explicitly specify lifetime // parameters. Most lifetime parameters are so called late-bound lifetimes // (ones that stick to input parameters) and Rust prohibits us from // specifying late-bound lifetimes explicitly (which is not a problem, // because those can always be correctly inferred). It would be possible to // explicitly specify early-bound lifetimes, but this is hardly useful. // Early-bound lifetimes are lifetimes that are only attached to the return // type. Something like: // // fn foo<'a>() -> &'a i32 // // It's hard to imagine how such a function would even work. So since those // functions are really rare and special, we won't support them. In // particular, for us to determine if a lifetime parameter is early- or // late-bound would be *really* difficult. // // So we just specify type parameters. In the future, however, we need to // add support for const parameters. But those are not remotely stable yet, // so we can wait a bit still. let generic_types = sig .generics .params .iter() .filter_map(|param| match param { GenericParam::Type(param) => { let name = ¶m.ident; Some(quote! { #name , }) } GenericParam::Const(param) => { let name = ¶m.ident; Some(quote! { #name , }) } GenericParam::Lifetime(_) => None, }) .collect::(); let generic_types = if generic_types.is_empty() { generic_types } else { quote! { ::<#generic_types> } }; // Generate the body of the function. This mainly depends on the self type, // but also on the proxy type. let fn_name = &sig.ident; let await_token = sig.asyncness.map(|_| quote! { .await }); let body = match self_arg { // Fn proxy types get a special treatment _ if proxy_type.is_fn() => { quote! { ({self})(#args) #await_token } } // No receiver SelfType::None => { // The proxy type is a reference, smart pointer or Box. quote! { #proxy_ty_param::#fn_name #generic_types(#args) #await_token } } // Receiver `self` (by value) SelfType::Value => { // The proxy type is a Box. quote! { #proxy_ty_param::#fn_name #generic_types(*self, #args) #await_token } } // `&self` or `&mut self` receiver SelfType::Ref | SelfType::Mut => { // The proxy type could be anything in the `Ref` case, and `&mut` // or Box in the `Mut` case. quote! { #proxy_ty_param::#fn_name #generic_types(self, #args) #await_token } } }; // Combine body with signature Ok(quote! { #(#attrs)* #sig { #body }}) } #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum SelfType { None, Ref, Mut, Value, } impl SelfType { fn from_sig(sig: &Signature) -> Self { match sig.inputs.iter().next() { Some(FnArg::Receiver(r)) => { if r.reference.is_none() { SelfType::Value } else if r.mutability.is_none() { SelfType::Ref } else { SelfType::Mut } } _ => SelfType::None, } } fn as_str(&self) -> Option<&'static str> { match *self { SelfType::None => None, SelfType::Ref => Some("&self"), SelfType::Mut => Some("&mut self"), SelfType::Value => Some("self"), } } } /// Checks if this method can be implemented for the given proxy type. If not, /// we will emit an error pointing to the method signature. fn check_receiver_compatible( proxy_type: &ProxyType, self_arg: SelfType, trait_name: &Ident, sig_span: Span2, ) -> syn::Result<()> { match (proxy_type, self_arg) { (ProxyType::Ref, SelfType::Mut) | (ProxyType::Ref, SelfType::Value) => { Err(Error::new( sig_span, format_args!("the trait `{}` cannot be auto-implemented for immutable references, because \ this method has a `{}` receiver (only `&self` and no receiver are allowed)", trait_name, self_arg.as_str().unwrap()), )) } (ProxyType::RefMut, SelfType::Value) => { Err(Error::new( sig_span, format_args!("the trait `{}` cannot be auto-implemented for mutable references, because \ this method has a `self` receiver (only `&self`, `&mut self` and no receiver are allowed)", trait_name,) )) } (ProxyType::Rc, SelfType::Mut) | (ProxyType::Rc, SelfType::Value) | (ProxyType::Arc, SelfType::Mut) | (ProxyType::Arc, SelfType::Value) => { let ptr_name = if *proxy_type == ProxyType::Rc { "Rc" } else { "Arc" }; Err(Error::new( sig_span, format_args!("the trait `{}` cannot be auto-implemented for {}, because \ this method has a `{}` receiver (only `&self` and no receiver are allowed)", trait_name, ptr_name, self_arg.as_str().unwrap()) )) } (ProxyType::Fn, _) | (ProxyType::FnMut, _) | (ProxyType::FnOnce, _) => { // The Fn-trait being compatible with the receiver was already // checked before (in `gen_fn_type_for_trait()`). Ok(()) } _ => Ok(()) // All other combinations are fine } } /// Generates a list of comma-separated arguments used to call the function. /// Currently, only simple names are valid and more complex pattern will lead /// to an error being emitted. `self` parameters are ignored. fn get_arg_list<'a>( original_inputs: impl Iterator, ) -> syn::Result<(Punctuated, TokenStream2)> { let mut args = TokenStream2::new(); let mut inputs = Punctuated::new(); let mut r: Result<(), Error> = Ok(()); for arg in original_inputs { match arg { FnArg::Typed(arg) => { // Make sure the argument pattern is a simple name. In // principle, we could probably support patterns, but it's // not that important now. if let Pat::Ident(PatIdent { by_ref: _by_ref, mutability: _mutability, ident, subpat: None, attrs, }) = &*arg.pat { // Add name plus trailing comma to tokens args.append_all(quote! { #ident , }); // Add an input argument that omits the `mut` and `ref` pattern bindings inputs.push(FnArg::Typed(PatType { attrs: arg.attrs.clone(), pat: Box::new(Pat::Ident(PatIdent { attrs: attrs.clone(), by_ref: None, mutability: None, ident: ident.clone(), subpat: None, })), colon_token: arg.colon_token, ty: arg.ty.clone(), })) } else { let err = Error::new( arg.pat.span(), "argument patterns are not supported by #[auto-impl]; use a simple name like \"foo\" (but not `_`)" ); if let Err(ref mut current_err) = r { current_err.combine(err); } else { r = Err(err); } continue; } } // There is only one such argument. We handle it elsewhere and // can ignore it here. FnArg::Receiver(arg) => { inputs.push(FnArg::Receiver(arg.clone())); } } } r.map(|_| (inputs, args)) } /// Checks if the given method has the attribute `#[auto_impl(keep_default_for(...))]` /// and if it contains the given proxy type. fn should_keep_default_for(m: &TraitItemFn, proxy_type: &ProxyType) -> syn::Result { // Get an iterator of just the attribute we are interested in. let mut it = m .attrs .iter() .filter(|attr| is_our_attr(attr)) .map(parse_our_attr); // Check the first (and hopefully only) `keep_default_for` attribute. let out = match it.next() { Some(attr) => { // Check if the attribute lists the given proxy type. let OurAttr::KeepDefaultFor(proxy_types) = attr?; proxy_types.contains(proxy_type) } // If there is no such attribute, we return `false` None => false, }; // Check if there is another such attribute (which we disallow) if it.next().is_some() { return Err(Error::new( m.sig.span(), "found two `keep_default_for` attributes on one method", )); } Ok(out) } fn filter_attrs(attrs: &[Attribute]) -> Vec { attrs .iter() .filter(|attr| attr.path().is_ident("cfg")) .cloned() .collect() } auto_impl-1.2.1/src/lib.rs000066400000000000000000000176601474133035000154210ustar00rootroot00000000000000//! A proc-macro attribute for automatically implementing a trait for //! references, some common smart pointers and closures. //! //! ## Simple example //! //! ``` //! use auto_impl::auto_impl; //! //! // This will generate two additional impl blocks: one `for &T` and one //! // `for Box` where `T: Foo`. //! #[auto_impl(&, Box)] //! trait Foo { //! fn foo(&self); //! } //! //! impl Foo for i32 { //! fn foo(&self) {} //! } //! //! fn requires_foo(_: impl Foo) {} //! //! //! requires_foo(0i32); // works: through the impl we defined above //! requires_foo(&0i32); // works: through the generated impl //! requires_foo(Box::new(0i32)); // works: through the generated impl //! ``` //! //! //! # Basic syntax and supported types //! //! You can annotate your trait with the `#[auto_impl(...)]` attribute. That //! attribute can only be used on traits and not on structs, enums or anything //! else. //! //! In the attribute, you have to specify all so called *proxy types* (the //! types you want to generate impls for) as a comma separated list. Each proxy //! type has a short abbreviation that you have to list there. //! //! Currently the following proxy types are supported: //! //! | Abbreviation | Example generated impl | //! | ------------ | ---------------------- | //! | `&` | `impl Trait for &T` | //! | `&mut` | `impl Trait for &mut T` | //! | `Box` | `impl Trait for Box` | //! | `Rc` | `impl Trait for Rc` | //! | `Arc` | `impl Trait for Arc` | //! | `Fn` | `impl Trait for T` | //! | `FnMut` | `impl Trait for T` | //! | `FnOnce` | `impl Trait for T` | //! //! //! # More examples //! //! More examples can be found in [the examples folder][examples]. In //! particular, the `greet_closure` example shows how to use the `Fn*` proxy //! types. //! //! [examples]: https://github.com/auto-impl-rs/auto_impl/tree/master/examples //! //! The following example shows that a trait can contain associated consts, //! associated types and complex methods (with generics, bounds, ...). //! //! ``` //! use auto_impl::auto_impl; //! use std::{fmt, rc::Rc}; //! //! //! #[auto_impl(&, &mut, Box, Rc)] //! trait Animal { //! const NUMBER_OF_LEGS: u8; //! //! type Name: fmt::Display; //! fn name(&self) -> Self::Name; //! //! fn select_favorite<'a, I>(&self, toys: I) -> &'a str //! where //! I: Iterator; //! } //! //! struct Dog(String); //! //! impl Animal for Dog { //! const NUMBER_OF_LEGS: u8 = 4; //! //! type Name = String; //! fn name(&self) -> Self::Name { //! self.0.clone() //! } //! //! fn select_favorite<'a, I>(&self, mut toys: I) -> &'a str //! where //! I: Iterator //! { //! toys.next().unwrap() //! } //! } //! //! fn require_animal(_: impl Animal) {} //! //! // All these calls work, as the `#[auto_impl]` attribute generated four //! // impls for all those proxy types //! require_animal(Dog("Doggo".into())); //! require_animal(&Dog("Doggo".into())); //! require_animal(&mut Dog("Doggo".into())); //! require_animal(Box::new(Dog("Doggo".into()))); //! require_animal(Rc::new(Dog("Doggo".into()))); //! ``` //! //! //! # Restriction of references and smart pointers //! //! Not every trait can be implemented for every proxy type. As an easy //! example, consider this trait: //! //! ``` //! trait Bar { //! fn bar(&mut self); //! } //! ``` //! //! If we try to implement it for immutable references via `#[auto_impl(&)]` //! the following impl would be generated: //! //! ```ignore //! impl Bar for &T { //! fn bar(&mut self) { //! T::bar(*self) // fails to compile //! } //! } //! ``` //! //! As you can easily see, this won't work because we can't call `bar` through //! an immutable reference. There are similar restrictions for many other //! smart pointers and references. //! //! In the following table you can see which methods can be implemented for //! which proxy type. If a trait contains at least one method that cannot be //! implemented for a proxy type, you cannot implement the trait for that proxy //! type. //! //! | Trait contains method with... | `&` | `&mut` | `Box` | `Rc` | `Arc` | //! | ----------------------------- | --- | ------ | ----- | ---- | ----- | //! | `&self` receiver | ✔ | ✔ | ✔ | ✔ | ✔ | //! | `&mut self` receiver | ✗ | ✔ | ✔ | ✗ | ✗ | //! | `self` receiver | ✗ | ✗ | ✔ | ✗ | ✗ | //! | no `self` receiver | ✔ | ✔ | ✔ | ✔ | ✔ | //! //! References and smart pointers have **no restriction in regard to associated //! types and associated consts**! Meaning: traits with associated types/consts //! can always be implemented for references and smart pointers as long as the //! methods of that trait can be implemented. //! //! //! # Restriction of closure types (`Fn*` traits) //! //! The `Fn*` proxy types have a lot more restrictions than references and //! smart pointer: //! - the trait must not define any associated types or consts //! - the trait must define **exactly one** method //! - the method must have a `self` receiver //! - the method must not return anything borrowed from `self` //! - the method must not have generic type or const parameters //! //! Additionally, some `Fn*` traits cannot be implemented for all `self` //! receiver types: //! //! | `self` Receiver | `Fn` | `FnMut` | `FnOnce` | //! | --------------- | ---- | ------- | -------- | //! | `&self` | ✔ | ✗ | ✗ | //! | `&mut self` | ✔ | ✔ | ✗ | //! | `self` | ✔ | ✔ | ✔ | //! //! Lastly, the impls generated for the `Fn*` proxy types contain `for T`. This //! is the most general blanket impl. So just be aware of the problems with //! coherence and orphan rules that can emerge due to this impl. //! //! //! # The `keep_default_for` attribute for methods //! //! By default, the impls generated by `auto_impl` will overwrite all methods //! of the trait, even those with default implementation. Sometimes, you want //! to not overwrite default methods and instead use the default //! implementation. You can do that by adding the //! `#[auto_impl(keep_default_for(...))]` attribute to a default method. In the //! parenthesis you need to list all proxy types for which the default method //! should be kept. //! //! From [the `keep_default_for` example]( //! https://github.com/auto-impl-rs/auto_impl/blob/master/examples/keep_default_for.rs): //! //! ``` //! # use auto_impl::auto_impl; //! #[auto_impl(&, Box)] //! trait Foo { //! fn required(&self) -> String; //! //! // The generated impl for `&T` will not override this method. //! #[auto_impl(keep_default_for(&))] //! fn provided(&self) { //! println!("Hello {}", self.required()); //! } //! } //! ``` extern crate proc_macro; #[macro_use] extern crate quote; use proc_macro::TokenStream; mod analyze; mod attr; mod gen; mod proxy; /// See crate documentation for more information. #[proc_macro_attribute] pub fn auto_impl(args: TokenStream, input: TokenStream) -> TokenStream { match auto_impl2(args, input.into()) { Ok(tokens) => tokens.into(), Err(e) => e.into_compile_error().into(), } } fn auto_impl2( args: TokenStream, input: proc_macro2::TokenStream, ) -> syn::Result { // Try to parse the token stream from the attribute to get a list of proxy // types. let proxy_types = proxy::parse_types(args); let mut trait_def = syn::parse2::(input)?; let generated = gen::gen_impls(&proxy_types, &trait_def)?; // Before returning the trait definition, we have to remove all // `#[auto_impl(...)]` attributes on all methods. attr::remove_our_attrs(&mut trait_def)?; Ok(quote!(#trait_def #generated)) } auto_impl-1.2.1/src/proxy.rs000066400000000000000000000106271474133035000160300ustar00rootroot00000000000000use std::iter::Peekable; use syn::Error; use crate::proc_macro::{token_stream, TokenStream, TokenTree}; /// Types for which a trait can automatically be implemented. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum ProxyType { Ref, RefMut, Arc, Rc, Box, Fn, FnMut, FnOnce, } impl ProxyType { pub(crate) fn is_fn(&self) -> bool { matches!(*self, ProxyType::Fn | ProxyType::FnMut | ProxyType::FnOnce) } } /// Parses the attribute token stream into a list of proxy types. /// /// The attribute token stream is the one in `#[auto_impl(...)]`. It is /// supposed to be a comma-separated list of possible proxy types. Legal values /// are `&`, `&mut`, `Box`, `Rc`, `Arc`, `Fn`, `FnMut` and `FnOnce`. /// /// If the given TokenStream is not valid, errors are emitted as appropriate. /// Erroneous types will not be put into the Vec but rather simply skipped, /// the emitted errors will abort the compilation anyway. pub(crate) fn parse_types(args: TokenStream) -> Vec { let mut out = Vec::new(); let mut iter = args.into_iter().peekable(); // While there are still tokens left... while iter.peek().is_some() { // First, we expect one of the proxy types. if let Ok(ty) = eat_type(&mut iter) { out.push(ty); } // If the next token is a comma, we eat it (trailing commas are // allowed). If not, nothing happens (in this case, it's probably the // end of the stream, otherwise an error will occur later). let comma_next = matches!(iter.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ','); if comma_next { let _ = iter.next(); } } out } /// Parses one `ProxyType` from the given token iterator. The iterator must not /// be empty! fn eat_type(iter: &mut Peekable) -> syn::Result { #[rustfmt::skip] const NOTE_TEXT: &str = "\ attribute format should be `#[auto_impl()]` where `` is \ a comma-separated list of types. Allowed values for types: `&`, \ `&mut`, `Box`, `Rc`, `Arc`, `Fn`, `FnMut` and `FnOnce`.\ "; const EXPECTED_TEXT: &str = "expected '&' or ident."; // We can unwrap because this function requires the iterator to be // non-empty. let ty = match iter.next().unwrap() { TokenTree::Group(group) => { return Err(Error::new( group.span().into(), format_args!("unexpected group, {}\n{}", EXPECTED_TEXT, NOTE_TEXT), )); } TokenTree::Literal(lit) => { return Err(Error::new( lit.span().into(), format_args!("unexpected literal, {}\n{}", EXPECTED_TEXT, NOTE_TEXT), )); } TokenTree::Punct(punct) => { // Only '&' are allowed. Everything else leads to an error. if punct.as_char() != '&' { return Err(Error::new( punct.span().into(), format_args!( "unexpected punctuation '{}', {}\n{}", punct, EXPECTED_TEXT, NOTE_TEXT ), )); } // Check if the next token is `mut`. If not, we will ignore it. let is_mut_next = matches!(iter.peek(), Some(TokenTree::Ident(id)) if id.to_string() == "mut"); if is_mut_next { // Eat `mut` let _ = iter.next(); ProxyType::RefMut } else { ProxyType::Ref } } TokenTree::Ident(ident) => match &*ident.to_string() { "Box" => ProxyType::Box, "Rc" => ProxyType::Rc, "Arc" => ProxyType::Arc, "Fn" => ProxyType::Fn, "FnMut" => ProxyType::FnMut, "FnOnce" => ProxyType::FnOnce, _ => { return Err(Error::new( ident.span().into(), format_args!("unexpected '{}', {}\n{}", ident, EXPECTED_TEXT, NOTE_TEXT), )); } }, }; Ok(ty) } // Right now, we can't really write useful tests. Many functions from // `proc_macro` use a compiler internal session. This session is only valid // when we were actually called as a proc macro. We need to add tests once // this limitation of `proc_macro` is fixed. auto_impl-1.2.1/tests/000077500000000000000000000000001474133035000146465ustar00rootroot00000000000000auto_impl-1.2.1/tests/compile-fail/000077500000000000000000000000001474133035000172075ustar00rootroot00000000000000auto_impl-1.2.1/tests/compile-fail/attr_on_enum.rs000066400000000000000000000001761474133035000222530ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&, &mut)] enum Foo { None, Name(String), Rgb(u8, u8, u8), } fn main() {} auto_impl-1.2.1/tests/compile-fail/attr_on_enum.stderr000066400000000000000000000001401474133035000231210ustar00rootroot00000000000000error: expected `trait` --> tests/compile-fail/attr_on_enum.rs:5:1 | 5 | enum Foo { | ^^^^ auto_impl-1.2.1/tests/compile-fail/attr_on_fn.rs000066400000000000000000000001431474133035000217040ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&, &mut)] fn foo(s: String) -> u32 { 3 } fn main() {} auto_impl-1.2.1/tests/compile-fail/attr_on_fn.stderr000066400000000000000000000001541474133035000225650ustar00rootroot00000000000000error: expected `trait` --> tests/compile-fail/attr_on_fn.rs:5:1 | 5 | fn foo(s: String) -> u32 { | ^^ auto_impl-1.2.1/tests/compile-fail/attr_on_impl_block.rs000066400000000000000000000001441474133035000234150ustar00rootroot00000000000000use auto_impl::auto_impl; trait Foo {} #[auto_impl(&, &mut)] impl Foo for usize {} fn main() {} auto_impl-1.2.1/tests/compile-fail/attr_on_impl_block.stderr000066400000000000000000000001611474133035000242730ustar00rootroot00000000000000error: expected `trait` --> tests/compile-fail/attr_on_impl_block.rs:7:1 | 7 | impl Foo for usize {} | ^^^^ auto_impl-1.2.1/tests/compile-fail/attr_on_struct.rs000066400000000000000000000001571474133035000226320ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&, &mut)] struct Foo { x: usize, bar: String, } fn main() {} auto_impl-1.2.1/tests/compile-fail/attr_on_struct.stderr000066400000000000000000000001461474133035000235070ustar00rootroot00000000000000error: expected `trait` --> tests/compile-fail/attr_on_struct.rs:5:1 | 5 | struct Foo { | ^^^^^^ auto_impl-1.2.1/tests/compile-fail/attr_on_type.rs000066400000000000000000000001241474133035000222610ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&, &mut)] type Baz = String; fn main() {} auto_impl-1.2.1/tests/compile-fail/attr_on_type.stderr000066400000000000000000000001501474133035000231370ustar00rootroot00000000000000error: expected `trait` --> tests/compile-fail/attr_on_type.rs:5:1 | 5 | type Baz = String; | ^^^^ auto_impl-1.2.1/tests/compile-fail/attr_on_unit_struct.rs000066400000000000000000000001341474133035000236640ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&, &mut)] struct Foo(usize, String); fn main() {} auto_impl-1.2.1/tests/compile-fail/attr_on_unit_struct.stderr000066400000000000000000000001711474133035000245440ustar00rootroot00000000000000error: expected `trait` --> tests/compile-fail/attr_on_unit_struct.rs:5:1 | 5 | struct Foo(usize, String); | ^^^^^^ auto_impl-1.2.1/tests/compile-fail/fn_associated_const.rs000066400000000000000000000001621474133035000235640ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Fn)] trait Foo { const LEN: usize; fn a(&self); } fn main() {} auto_impl-1.2.1/tests/compile-fail/fn_associated_const.stderr000066400000000000000000000004221474133035000244420ustar00rootroot00000000000000error: this trait cannot be auto-implemented for Fn-traits (only traits with exactly one method and no other items are allowed) --> tests/compile-fail/fn_associated_const.rs:5:1 | 5 | / trait Foo { 6 | | const LEN: usize; 7 | | 8 | | fn a(&self); 9 | | } | |_^ auto_impl-1.2.1/tests/compile-fail/fn_associated_type.rs000066400000000000000000000001521474133035000234160ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Fn)] trait Foo { type Out; fn a(&self); } fn main() {} auto_impl-1.2.1/tests/compile-fail/fn_associated_type.stderr000066400000000000000000000004111474133035000242730ustar00rootroot00000000000000error: this trait cannot be auto-implemented for Fn-traits (only traits with exactly one method and no other items are allowed) --> tests/compile-fail/fn_associated_type.rs:5:1 | 5 | / trait Foo { 6 | | type Out; 7 | | 8 | | fn a(&self); 9 | | } | |_^ auto_impl-1.2.1/tests/compile-fail/fn_const_generics.rs000066400000000000000000000001761474133035000232510ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Fn)] trait Greeter { fn greet(&self, id: usize); } fn main() {} auto_impl-1.2.1/tests/compile-fail/fn_const_generics.stderr000066400000000000000000000003551474133035000241270ustar00rootroot00000000000000error: the trait 'Greeter' cannot be implemented for Fn-traits: constant arguments are not allowed --> tests/compile-fail/fn_const_generics.rs:6:14 | 6 | fn greet(&self, id: usize); | ^^^^^^^^^^^^^^ auto_impl-1.2.1/tests/compile-fail/fn_generics.rs000066400000000000000000000002171474133035000220370ustar00rootroot00000000000000use std::fmt::Display; use auto_impl::auto_impl; #[auto_impl(Fn)] trait Greeter { fn greet(&self, name: T); } fn main() {} auto_impl-1.2.1/tests/compile-fail/fn_generics.stderr000066400000000000000000000006431474133035000227210ustar00rootroot00000000000000error: the trait 'Greeter' cannot be implemented for Fn-traits: generic arguments are not allowed --> tests/compile-fail/fn_generics.rs:7:14 | 7 | fn greet(&self, name: T); | ^^^^^^^^^^ warning: unused import: `std::fmt::Display` --> tests/compile-fail/fn_generics.rs:1:5 | 1 | use std::fmt::Display; | ^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default auto_impl-1.2.1/tests/compile-fail/fn_multiple_methods.rs000066400000000000000000000001541474133035000236160ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Fn)] trait Foo { fn a(&self); fn b(&self); } fn main() {} auto_impl-1.2.1/tests/compile-fail/fn_multiple_methods.stderr000066400000000000000000000004071474133035000244760ustar00rootroot00000000000000error: this trait cannot be auto-implemented for Fn-traits (only traits with exactly one method and no other items are allowed) --> tests/compile-fail/fn_multiple_methods.rs:5:1 | 5 | / trait Foo { 6 | | fn a(&self); 7 | | fn b(&self); 8 | | } | |_^ auto_impl-1.2.1/tests/compile-fail/fn_unsafe_method.rs000066400000000000000000000001421474133035000230560ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Fn)] trait Foo { unsafe fn a(&self); } fn main() {} auto_impl-1.2.1/tests/compile-fail/fn_unsafe_method.stderr000066400000000000000000000002611474133035000237370ustar00rootroot00000000000000error: the trait 'Foo' cannot be auto-implemented for Fn-traits: unsafe methods are not allowed --> $DIR/fn_unsafe_method.rs:6:5 | 6 | unsafe fn a(&self); | ^^^^^^ auto_impl-1.2.1/tests/compile-fail/keep_default_for_on_assoc_type.rs000066400000000000000000000001751474133035000260030ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&)] trait Foo { #[auto_impl(keep_default_for(&))] type Foo; } fn main() {} auto_impl-1.2.1/tests/compile-fail/keep_default_for_on_assoc_type.stderr000066400000000000000000000003231474133035000266550ustar00rootroot00000000000000error: `#[auto_impl]` attributes are only allowed on methods --> tests/compile-fail/keep_default_for_on_assoc_type.rs:6:5 | 6 | / #[auto_impl(keep_default_for(&))] 7 | | type Foo; | |_____________^ auto_impl-1.2.1/tests/compile-fail/keep_default_for_on_required_method.rs000066400000000000000000000002071474133035000270060ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&)] trait Foo { #[auto_impl(keep_default_for(&))] fn required(&self); } fn main() {} auto_impl-1.2.1/tests/compile-fail/keep_default_for_on_required_method.stderr000066400000000000000000000003621474133035000276670ustar00rootroot00000000000000error: the method `required` has the attribute `keep_default_for` but is not a default method (no body is provided) --> tests/compile-fail/keep_default_for_on_required_method.rs:7:5 | 7 | fn required(&self); | ^^^^^^^^^^^^^^^^^^ auto_impl-1.2.1/tests/compile-fail/method_attr_invalid.rs000066400000000000000000000001741474133035000235770ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&)] trait Foo { #[auto_impl(ferris_for_life)] fn a(&self); } fn main() {} auto_impl-1.2.1/tests/compile-fail/method_attr_invalid.stderr000066400000000000000000000003071474133035000244540ustar00rootroot00000000000000error: expected arguments for 'ferris_for_life' in parenthesis `()`, found nothing --> $DIR/method_attr_invalid.rs:6:17 | 6 | #[auto_impl(ferris_for_life)] | ^^^^^^^^^^^^^^^ auto_impl-1.2.1/tests/compile-fail/mut_self_for_arc.rs000066400000000000000000000001421474133035000230630ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Arc)] trait Foo { fn foo(&mut self); } fn main() {} auto_impl-1.2.1/tests/compile-fail/mut_self_for_arc.stderr000066400000000000000000000003761474133035000237530ustar00rootroot00000000000000error: the trait `Foo` cannot be auto-implemented for Arc, because this method has a `&mut self` receiver (only `&self` and no receiver are allowed) --> tests/compile-fail/mut_self_for_arc.rs:6:5 | 6 | fn foo(&mut self); | ^^^^^^^^^^^^^^^^^ auto_impl-1.2.1/tests/compile-fail/mut_self_for_immutable_ref.rs000066400000000000000000000001401474133035000251270ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&)] trait Foo { fn foo(&mut self); } fn main() {} auto_impl-1.2.1/tests/compile-fail/mut_self_for_immutable_ref.stderr000066400000000000000000000004311474133035000260110ustar00rootroot00000000000000error: the trait `Foo` cannot be auto-implemented for immutable references, because this method has a `&mut self` receiver (only `&self` and no receiver are allowed) --> tests/compile-fail/mut_self_for_immutable_ref.rs:6:5 | 6 | fn foo(&mut self); | ^^^^^^^^^^^^^^^^^ auto_impl-1.2.1/tests/compile-fail/mut_self_for_rc.rs000066400000000000000000000001411474133035000227210ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Rc)] trait Foo { fn foo(&mut self); } fn main() {} auto_impl-1.2.1/tests/compile-fail/mut_self_for_rc.stderr000066400000000000000000000003741474133035000236100ustar00rootroot00000000000000error: the trait `Foo` cannot be auto-implemented for Rc, because this method has a `&mut self` receiver (only `&self` and no receiver are allowed) --> tests/compile-fail/mut_self_for_rc.rs:6:5 | 6 | fn foo(&mut self); | ^^^^^^^^^^^^^^^^^ auto_impl-1.2.1/tests/compile-fail/super_trait_not_implemented.rs000066400000000000000000000004721474133035000253640ustar00rootroot00000000000000use auto_impl::auto_impl; trait Supi {} #[auto_impl(Box, &)] trait Foo: Supi {} struct Dog; impl Supi for Dog {} impl Foo for Dog {} fn requires_foo(_: T) {} fn main() { requires_foo(Dog); // should work requires_foo(Box::new(Dog)); // shouldn't, because `Box: Supi` is not satisfied } auto_impl-1.2.1/tests/compile-fail/super_trait_not_implemented.stderr000066400000000000000000000021621474133035000262410ustar00rootroot00000000000000error[E0277]: the trait bound `Box: Foo` is not satisfied --> tests/compile-fail/super_trait_not_implemented.rs:18:18 | 18 | requires_foo(Box::new(Dog)); // shouldn't, because `Box: Supi` is not satisfied | ------------ ^^^^^^^^^^^^^ the trait `Supi` is not implemented for `Box` | | | required by a bound introduced by this call | note: required for `Box` to implement `Foo` --> tests/compile-fail/super_trait_not_implemented.rs:5:1 | 5 | #[auto_impl(Box, &)] | ^^^^^^^^^^^^^^^^^^^^ 6 | trait Foo: Supi {} | ^^^ ---- unsatisfied trait bound introduced here note: required by a bound in `requires_foo` --> tests/compile-fail/super_trait_not_implemented.rs:14:20 | 14 | fn requires_foo(_: T) {} | ^^^ required by this bound in `requires_foo` = note: this error originates in the attribute macro `auto_impl` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider dereferencing here | 18 | requires_foo(*Box::new(Dog)); // shouldn't, because `Box: Supi` is not satisfied | + auto_impl-1.2.1/tests/compile-fail/trait_obj_value_self.rs000066400000000000000000000002431474133035000237360ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Box)] trait Trait { fn foo(self); } fn assert_impl() {} fn main() { assert_impl::>(); } auto_impl-1.2.1/tests/compile-fail/trait_obj_value_self.stderr000066400000000000000000000016441474133035000246230ustar00rootroot00000000000000error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time --> tests/compile-fail/trait_obj_value_self.rs:12:19 | 12 | assert_impl::>(); | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn Trait` = help: the trait `Trait` is implemented for `Box` note: required for `Box` to implement `Trait` --> tests/compile-fail/trait_obj_value_self.rs:4:1 | 4 | #[auto_impl(Box)] | ^^^^^^^^^^^^^^^^^ 5 | trait Trait { | ^^^^^ note: required by a bound in `assert_impl` --> tests/compile-fail/trait_obj_value_self.rs:9:19 | 9 | fn assert_impl() {} | ^^^^^ required by this bound in `assert_impl` = note: this error originates in the attribute macro `auto_impl` (in Nightly builds, run with -Z macro-backtrace for more info) auto_impl-1.2.1/tests/compile-fail/value_self_for_immutable_ref.rs000066400000000000000000000001331474133035000254400ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&)] trait Foo { fn foo(self); } fn main() {} auto_impl-1.2.1/tests/compile-fail/value_self_for_immutable_ref.stderr000066400000000000000000000004141474133035000263210ustar00rootroot00000000000000error: the trait `Foo` cannot be auto-implemented for immutable references, because this method has a `self` receiver (only `&self` and no receiver are allowed) --> tests/compile-fail/value_self_for_immutable_ref.rs:6:5 | 6 | fn foo(self); | ^^^^^^^^^^^^ auto_impl-1.2.1/tests/compile-fail/value_self_for_mutable_ref.rs000066400000000000000000000001361474133035000251150ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&mut)] trait Foo { fn foo(self); } fn main() {} auto_impl-1.2.1/tests/compile-fail/value_self_for_mutable_ref.stderr000066400000000000000000000004251474133035000257750ustar00rootroot00000000000000error: the trait `Foo` cannot be auto-implemented for mutable references, because this method has a `self` receiver (only `&self`, `&mut self` and no receiver are allowed) --> tests/compile-fail/value_self_for_mutable_ref.rs:6:5 | 6 | fn foo(self); | ^^^^^^^^^^^^ auto_impl-1.2.1/tests/compile-pass/000077500000000000000000000000001474133035000172425ustar00rootroot00000000000000auto_impl-1.2.1/tests/compile-pass/big_trait_for_all_refs.rs000066400000000000000000000004511474133035000242710ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Arc, Box, Rc, &, &mut)] trait RefTrait1<'a, T: for<'b> Into<&'b str>> { type Type1; type Type2; const FOO: u32; fn execute1<'b>(&'a self, arg1: &'b T) -> Result; fn execute2(&self) -> Self::Type2; } fn main() {} auto_impl-1.2.1/tests/compile-pass/big_trait_for_box.rs000066400000000000000000000006371474133035000233000ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Box)] trait BoxTrait1<'a, T: for<'b> Into<&'b str>> { type Type1; type Type2; const FOO: u32; fn execute1<'b>(&'a self, arg1: &'b T) -> Result; fn execute2(&mut self, arg1: i32) -> Self::Type2; fn execute3(self) -> Self::Type1; fn execute4(arg1: String) -> Result; fn execute5() -> String; } fn main() {} auto_impl-1.2.1/tests/compile-pass/big_trait_where_bound_for_all_refs.rs000066400000000000000000000007041474133035000266530ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Arc, Box, Rc, &, &mut)] trait Big<'a, T: for<'b> Into<&'b str>> { type Type1; type Type2: std::ops::Deref; const FOO: u32; fn execute1<'b>(&'a self, arg1: &'b T) -> Result where T: Clone, ::Target: Clone; fn execute2(&self) -> Self::Type2 where T: std::ops::Deref; } fn main() {} auto_impl-1.2.1/tests/compile-pass/fn_method_lifetimes.rs000066400000000000000000000003421474133035000236130ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Fn)] trait FnTrait2<'a, T> { fn execute<'b, 'c>( &'a self, arg1: &'b T, arg2: &'c T, arg3: &'static str, ) -> Result; } fn main() {} auto_impl-1.2.1/tests/compile-pass/generic_fn_method_for_refs.rs000066400000000000000000000003001474133035000251250ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&, Arc)] pub trait OrderStoreFilter { fn filter(&self, predicate: F) -> Result where F: Fn(&str) -> bool; } fn main() {} auto_impl-1.2.1/tests/compile-pass/generic_types_and_lifetimes_for_fn.rs000066400000000000000000000002511474133035000266620ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Fn)] trait MyTrait<'a, T> { fn execute<'b>(&'a self, arg1: &'b T, arg2: &'static str) -> Result<(), String>; } fn main() {} auto_impl-1.2.1/tests/compile-pass/generic_types_and_lifetimes_for_refs.rs000066400000000000000000000002561474133035000272230ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&, &mut)] trait MyTrait<'a, T> { fn execute<'b>(&'a self, arg1: &'b T, arg2: &'static str) -> Result<(), String>; } fn main() {} auto_impl-1.2.1/tests/compile-pass/keep_default_for_simple.rs000066400000000000000000000002421474133035000244550ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&)] trait Foo { fn required(&self); #[auto_impl(keep_default_for(&))] fn provided(&self) {} } fn main() {} auto_impl-1.2.1/tests/compile-pass/keep_default_for_with_where_bounds.rs000066400000000000000000000002641474133035000267070ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&)] trait Foo { fn required(&self); #[auto_impl(keep_default_for(&))] fn provided(&self) where Self: Clone {} } fn main() {} auto_impl-1.2.1/tests/compile-pass/method_name_shadowing.rs000066400000000000000000000011351474133035000241330ustar00rootroot00000000000000use auto_impl::auto_impl; trait AllExt { fn foo(&self, _: i32); } impl AllExt for T { fn foo(&self, _: i32) {} } // This will expand to: // // impl Foo for &T { // fn foo(&self, _x: bool) { // T::foo(self, _x) // } // } // // With this test we want to make sure, that the call `T::foo` is always // unambiguous. Luckily, Rust is nice here. And if we only know `T: Foo`, then // other global functions are not even considered. Having a test for this // doesn't hurt though. #[auto_impl(&)] trait Foo { fn foo(&self, _x: bool); } fn main() {} auto_impl-1.2.1/tests/compile-pass/mut_self_for_fn.rs000066400000000000000000000002451474133035000227600ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Fn)] trait Foo { fn execute(&mut self); } fn foo(_: impl Foo) {} fn bar() { // Fn foo(|| {}); } fn main() {} auto_impl-1.2.1/tests/compile-pass/mut_self_for_fn_mut.rs000066400000000000000000000003351474133035000236450ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(FnMut)] trait Foo { fn execute(&mut self); } fn foo(_: impl Foo) {} fn bar() { // FnMut let mut x = 0; foo(|| x += 1); // Fn foo(|| {}); } fn main() {} auto_impl-1.2.1/tests/compile-pass/non_inferred_generic_types_for_all_refs.rs000066400000000000000000000001571474133035000277200ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&)] trait Foo { fn foo(); fn bar(&self); } fn main() {} auto_impl-1.2.1/tests/compile-pass/non_inferred_generic_types_for_box.rs000066400000000000000000000002401474133035000267120ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Box)] trait Foo { fn foo(); fn bar(&self); fn baz(&mut self); fn qux(self); } fn main() {} auto_impl-1.2.1/tests/compile-pass/non_inferred_generic_types_with_lifetimes_for_all_refs.rs000066400000000000000000000003261474133035000330120ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&)] trait Foo { fn foo(); fn bar(&self); fn baz<'a, U>() -> &'a str; fn qux<'a, 'b, 'c, U, V, T>(&self) -> (&'a str, &'b str, &'c str); } fn main() {} auto_impl-1.2.1/tests/compile-pass/ref_self_for_fn.rs000066400000000000000000000002411474133035000227230ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Fn)] trait Foo { fn execute(&self); } fn foo(_: impl Foo) {} fn bar() { // Fn foo(|| {}); } fn main() {} auto_impl-1.2.1/tests/compile-pass/self_bound.rs000066400000000000000000000004671474133035000217370ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&)] trait Trait { fn foo(&self) where Self: Clone; } #[derive(Clone)] struct Foo {} impl Trait for Foo { fn foo(&self) where Self: Clone, {} } fn assert_impl() {} fn main() { assert_impl::(); assert_impl::<&Foo>(); } auto_impl-1.2.1/tests/compile-pass/self_bound_default_method.rs000066400000000000000000000005171474133035000247770ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Box)] trait Trait { fn bar(&self); #[auto_impl(keep_default_for(Box))] fn foo(&self) where Self: Clone {} } fn assert_impl() {} struct Foo {} impl Trait for Foo { fn bar(&self) {} } fn main() { assert_impl::(); assert_impl::>(); } auto_impl-1.2.1/tests/compile-pass/self_bound_multiple.rs000066400000000000000000000011121474133035000236360ustar00rootroot00000000000000use std::fmt; use auto_impl::auto_impl; #[auto_impl(&)] trait Trait { fn foo(&self) where Self: Clone; fn bar(&self) where Self: Default + fmt::Display; } #[derive(Clone, Default)] struct Foo {} impl Trait for Foo { fn foo(&self) where Self: Clone, {} fn bar(&self) where Self: Default + fmt::Display, {} } impl fmt::Display for Foo { fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { unimplemented!() } } fn assert_impl() {} fn main() { assert_impl::(); assert_impl::<&Foo>(); } auto_impl-1.2.1/tests/compile-pass/self_by_value_mut.rs000066400000000000000000000003301474133035000233100ustar00rootroot00000000000000use auto_impl::auto_impl; struct Data { id: usize, } #[auto_impl(&, Box)] trait Foo { #[auto_impl(keep_default_for(&))] fn foo(&self, ref mut data: Data) { data.id += 1; } } fn main() {} auto_impl-1.2.1/tests/compile-pass/super_trait_complex_for_refs.rs000066400000000000000000000003711474133035000255660ustar00rootroot00000000000000use auto_impl::auto_impl; trait Supi<'a, T> { fn supi(&self); } #[auto_impl(Box, &)] trait Foo: Supi<'static, U> where Self: Send { fn foo(&self) -> i32 { self.supi(); 3 } fn bar(&self); } fn main() {} auto_impl-1.2.1/tests/compile-pass/super_trait_simple_for_fn_types.rs000066400000000000000000000002031474133035000262720ustar00rootroot00000000000000use auto_impl::auto_impl; trait Supi {} #[auto_impl(Fn)] trait Foo: Supi { fn foo(&self, x: u32) -> String; } fn main() {} auto_impl-1.2.1/tests/compile-pass/super_trait_simple_for_refs.rs000066400000000000000000000001411474133035000254030ustar00rootroot00000000000000use auto_impl::auto_impl; trait Supi {} #[auto_impl(Box, &)] trait Foo: Supi {} fn main() {} auto_impl-1.2.1/tests/compile-pass/trailing_comma.rs000066400000000000000000000001171474133035000225740ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&)] trait MyTrait {} fn main() { } auto_impl-1.2.1/tests/compile-pass/trait_in_fn.rs000066400000000000000000000007311474133035000221050ustar00rootroot00000000000000 fn foo() { use auto_impl::auto_impl; #[auto_impl(Fn)] trait Foo<'a, T> { fn execute<'b>( &'a self, arg1: &'b T, arg3: &'static str, ) -> Result; } #[auto_impl(&, &mut, Box, Rc, Arc)] trait Bar<'a, T> { fn execute<'b>( &'a self, arg1: &'b T, arg3: &'static str, ) -> Result; } println!("yooo"); } fn main() {} auto_impl-1.2.1/tests/compile-pass/trait_in_mods.rs000066400000000000000000000030171474133035000224440ustar00rootroot00000000000000// Make sure that everything compiles even without the prelude. This basically // forces us to generate full paths for types of the standard/core library. // // Note that `no_implicit_prelude` attribute appears to interact strangely // with Rust's 2018 style modules and extern crates. #![no_implicit_prelude] extern crate std; extern crate auto_impl; mod outer { use crate::{ auto_impl::auto_impl, std::{ string::String, result::Result, } }; #[auto_impl(Fn)] trait Foo<'a, T> { fn execute<'b>( &'a self, arg1: &'b T, arg3: &'static str, ) -> Result; } #[auto_impl(&, &mut, Box, Rc, Arc)] trait Bar<'a, T> { fn execute<'b>( &'a self, arg1: &'b T, arg3: &'static str, ) -> Result; } mod inner { use crate::{ auto_impl::auto_impl, std::{ string::String, result::Result, } }; #[auto_impl(Fn)] trait Foo<'a, T> { fn execute<'b>( &'a self, arg1: &'b T, arg3: &'static str, ) -> Result; } #[auto_impl(&, &mut, Box, Rc, Arc)] trait Bar<'a, T> { fn execute<'b>( &'a self, arg1: &'b T, arg3: &'static str, ) -> Result; } } } fn main() {} auto_impl-1.2.1/tests/compile-pass/trait_obj_default_method.rs000066400000000000000000000005101474133035000246250ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Box)] trait Trait { fn bar(&self); #[auto_impl(keep_default_for(Box))] fn foo(self) where Self: Sized {} } fn assert_impl() {} struct Foo {} impl Trait for Foo { fn bar(&self) {} } fn main() { assert_impl::(); assert_impl::>(); } auto_impl-1.2.1/tests/compile-pass/trait_obj_immutable_self.rs000066400000000000000000000005501474133035000246350ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&, &mut, Box, Rc, Arc)] trait Trait { fn foo(&self); } fn assert_impl() {} fn main() { use std::{rc::Rc, sync::Arc}; assert_impl::<&dyn Trait>(); assert_impl::<&mut dyn Trait>(); assert_impl::>(); assert_impl::>(); assert_impl::>(); } auto_impl-1.2.1/tests/compile-pass/trait_obj_self_sized.rs000066400000000000000000000003701474133035000237740ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Box)] trait Foo: Sized { fn foo(&self); } #[auto_impl(Box)] trait Bar where Self: Sized { fn foo(&self); } #[auto_impl(Box)] trait Baz: Sized where Self: Sized { fn foo(&self); } fn main() {} auto_impl-1.2.1/tests/compile-pass/trait_obj_value_self.rs000066400000000000000000000001371474133035000237730ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Box)] trait Trait { fn foo(self); } fn main() {} auto_impl-1.2.1/tests/compile-pass/value_self_for_fn.rs000066400000000000000000000002401474133035000232620ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(Fn)] trait Foo { fn execute(self); } fn foo(_: impl Foo) {} fn bar() { // Fn foo(|| {}); } fn main() {} auto_impl-1.2.1/tests/compile-pass/value_self_for_fn_mut.rs000066400000000000000000000003301474133035000241470ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(FnMut)] trait Foo { fn execute(self); } fn foo(_: impl Foo) {} fn bar() { // FnMut let mut x = 0; foo(|| x += 1); // Fn foo(|| {}); } fn main() {} auto_impl-1.2.1/tests/compile-pass/value_self_for_fn_once.rs000066400000000000000000000004301474133035000242670ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(FnOnce)] trait Foo { fn execute(self); } fn foo(_: impl Foo) {} fn bar() { // FnOnce let s = String::new(); foo(|| drop(s)); // FnMut let mut x = 0; foo(|| x += 1); // Fn foo(|| {}); } fn main() {} auto_impl-1.2.1/tests/no_std.rs000066400000000000000000000004761474133035000165110ustar00rootroot00000000000000#![no_std] #![allow(dead_code)] use auto_impl::auto_impl; mod core {} mod alloc {} struct Box; struct Rc; struct Arc; struct Fn; struct FnMut; #[auto_impl(&, &mut, Box, Rc, Arc)] trait Test {} #[auto_impl(Fn)] trait TestFn { fn test(&self); } #[auto_impl(FnMut)] trait TestFnMut { fn test(&mut self); } auto_impl-1.2.1/tests/since_1.51/000077500000000000000000000000001474133035000164135ustar00rootroot00000000000000auto_impl-1.2.1/tests/since_1.51/compile-pass/000077500000000000000000000000001474133035000210075ustar00rootroot00000000000000auto_impl-1.2.1/tests/since_1.51/compile-pass/associated_lifetime.rs000066400000000000000000000001651474133035000253540ustar00rootroot00000000000000#[auto_impl::auto_impl(&, Arc, Box)] pub trait Trait { type Type<'a, T>: Iterator + 'a; } fn main() {}auto_impl-1.2.1/tests/since_1.51/compile-pass/generic_const_method.rs000066400000000000000000000001521474133035000255350ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&)] trait Foo { fn foo(&self); } fn main() {} auto_impl-1.2.1/tests/since_1.51/compile-pass/generic_mix.rs000066400000000000000000000003121474133035000236420ustar00rootroot00000000000000use auto_impl::auto_impl; #[auto_impl(&, &mut)] trait MyTrait<'a, T> { fn execute<'b, U, const N: usize>(&'a self, arg1: &'b T, arg2: &'static str, arg3: U) -> Result<(), String>; } fn main() {} auto_impl-1.2.1/tests/since_1.75/000077500000000000000000000000001474133035000164215ustar00rootroot00000000000000auto_impl-1.2.1/tests/since_1.75/compile-pass/000077500000000000000000000000001474133035000210155ustar00rootroot00000000000000auto_impl-1.2.1/tests/since_1.75/compile-pass/async_trait.rs000066400000000000000000000001531474133035000237020ustar00rootroot00000000000000#[auto_impl::auto_impl(&, &mut, Arc, Box, Rc)] trait AsyncTrait { async fn foo(&self); } fn main() {} auto_impl-1.2.1/tests/ui.rs000066400000000000000000000010711474133035000156300ustar00rootroot00000000000000use trybuild::TestCases; #[test] fn ui_compile_pass() { let t = TestCases::new(); t.pass("tests/compile-pass/*.rs"); } #[rustversion::nightly] #[test] fn ui_compile_fail() { let t = TestCases::new(); t.compile_fail("tests/compile-fail/*.rs"); } #[rustversion::since(1.51)] #[test] fn ui_since_1_51_compile_pass() { let t = TestCases::new(); t.pass("tests/since_1.51/compile-pass/*.rs"); } #[rustversion::since(1.75)] #[test] fn ui_since_1_75_compile_pass() { let t = TestCases::new(); t.pass("tests/since_1.75/compile-pass/*.rs"); }