-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #38 from LukasKalbertodt/docs
Add crate documentation and update README
- Loading branch information
Showing
7 changed files
with
282 additions
and
191 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,216 +1,50 @@ | ||
# `auto_impl` [![Join the chat at https://gitter.im/auto-impl-rs/Lobby](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/auto-impl-rs/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://travis-ci.org/auto-impl-rs/auto_impl.svg?branch=master)](https://travis-ci.org/auto-impl-rs/auto_impl) [![Crates.io](https://img.shields.io/crates/v/auto_impl.svg)](https://crates.io/crates/auto_impl) | ||
# `auto_impl` [![Join the chat at https://gitter.im/auto-impl-rs/Lobby](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/auto-impl-rs/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://travis-ci.org/auto-impl-rs/auto_impl.svg?branch=master)](https://travis-ci.org/auto-impl-rs/auto_impl) [![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 simple compiler plugin for automatically implementing a trait for some common smart pointers and closures. | ||
A proc-macro attribute for automatically implementing a trait for references, | ||
some common smart pointers and closures. | ||
|
||
# Usage | ||
|
||
This library requires the `nightly` channel. | ||
This library requires Rust 1.30.0 or newer. | ||
|
||
Add `auto_impl` to your `Cargo.toml`: | ||
|
||
``` | ||
auto_impl = "*" | ||
``` | ||
|
||
Reference in your crate root: | ||
Add `auto_impl` to your `Cargo.toml` and just use it in your crate: | ||
|
||
```rust | ||
#![feature(proc_macro)] | ||
|
||
extern crate auto_impl; | ||
|
||
// 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: | ||
|
||
```rust | ||
#[auto_impl(&, Arc)] | ||
pub trait OrderStoreFilter { | ||
fn filter<F>(&self, predicate: F) -> Result<Iter, Error> | ||
where | ||
F: Fn(&OrderData) -> bool; | ||
} | ||
``` | ||
|
||
Now anywhere that requires a `T: OrderStoreFilter` will also accept an `&T` or `Arc<T>` where `T` implements `OrderStoreFilter`. | ||
|
||
## Specifics | ||
|
||
The following types are supported and can be freely combined: | ||
|
||
- [`Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html) | ||
- [`Rc`](https://doc.rust-lang.org/std/rc/struct.Rc.html) | ||
- [`Box`](https://doc.rust-lang.org/std/boxed/struct.Box.html) | ||
|
||
The following types are also supported, but require a blanket implementation (you can only have one of these per `trait`): | ||
|
||
- [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html) | ||
- [`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html) | ||
- [`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html) | ||
- `&` | ||
- `&mut` | ||
|
||
## Implement a trait for `Box` | ||
|
||
```rust | ||
#[auto_impl(Box)] | ||
trait MyTrait<'a, T> | ||
where T: AsRef<str> | ||
{ | ||
type Type1; | ||
type Type2; | ||
|
||
fn execute1<'b>(&'a self, arg1: &'b T) -> Result<Self::Type1, String>; | ||
fn execute2(&self) -> Self::Type2; | ||
fn execute3(self) -> Self::Type1; | ||
fn execute4() -> &'static str; | ||
} | ||
``` | ||
|
||
Will expand to: | ||
|
||
```rust | ||
impl<'a, T, TAutoImpl> MyTrait<'a, T> for ::std::boxed::Box<TAutoImpl> | ||
where TAutoImpl: MyTrait<'a, T>, | ||
T: AsRef<str> | ||
{ | ||
type Type1 = TAutoImpl::Type1; | ||
type Type2 = TAutoImpl::Type2; | ||
|
||
fn execute1<'b>(&'a self, arg1: &'b T) -> Result<Self::Type1, String> { | ||
(**self).execute1(arg1) | ||
} | ||
|
||
fn execute2(&self) -> Self::Type2 { | ||
(**self).execute2() | ||
} | ||
|
||
fn execute3(self) -> Self::Type1 { | ||
(*self).execute3() | ||
} | ||
|
||
fn execute4() -> &'static str { | ||
TAutoImpl::execute4() | ||
} | ||
} | ||
``` | ||
|
||
There are no restrictions on `auto_impl` for `Box`. | ||
|
||
## Implement a trait for a smart pointer | ||
|
||
Add the `#[auto_impl]` attribute to traits to automatically implement them for wrapper types: | ||
|
||
```rust | ||
#[auto_impl(Arc, Rc)] | ||
trait MyTrait<'a, T> | ||
where T: AsRef<str> | ||
{ | ||
type Type1; | ||
type Type2; | ||
|
||
fn execute1<'b>(&'a self, arg1: &'b T) -> Result<Self::Type1, String>; | ||
fn execute2(&self) -> Self::Type2; | ||
} | ||
``` | ||
|
||
Will expand to: | ||
|
||
```rust | ||
impl<'a, T, TAutoImpl> MyTrait<'a, T> for ::std::sync::Arc<TAutoImpl> | ||
where TAutoImpl: MyTrait<'a, T>, | ||
T: AsRef<str> | ||
{ | ||
type Type1 = TAutoImpl::Type1; | ||
type Type2 = TAutoImpl::Type2; | ||
|
||
fn execute1<'b>(&'a self, arg1: &'b T) -> Result<Self::Type1, String> { | ||
(**self).execute1(arg1) | ||
} | ||
|
||
fn execute2(&self) -> Self::Type2 { | ||
(**self).execute2() | ||
} | ||
} | ||
|
||
impl<'a, T, TAutoImpl> MyTrait<'a, T> for ::std::rc::Rc<TAutoImpl> | ||
where TAutoImpl: MyTrait<'a, T>, | ||
T: AsRef<str> | ||
{ | ||
type Type1 = TAutoImpl::Type1; | ||
type Type2 = TAutoImpl::Type2; | ||
|
||
fn execute1<'b>(&'a self, arg1: &'b T) -> Result<Self::Type1, String> { | ||
(**self).execute1(arg1) | ||
} | ||
|
||
fn execute2(&self) -> Self::Type2 { | ||
(**self).execute2() | ||
} | ||
} | ||
``` | ||
|
||
There are a few restrictions on `#[auto_impl]` for smart pointers. The trait must: | ||
|
||
- Only have methods that take `&self` or have no receiver (static) | ||
|
||
## Implement a trait for a closure | ||
Add an `auto_impl` attribute to traits you want to automatically implement for wrapper types. Here is a small example: | ||
|
||
```rust | ||
#[auto_impl(Fn)] | ||
trait MyTrait<'a, T> { | ||
fn execute<'b>(&'a self, arg1: &'b T, arg2: &'static str) -> Result<(), String>; | ||
// This will generate two additional impl blocks: one for `&T` and one | ||
// for `Box<T>` where `T: Foo`. | ||
#[auto_impl(&, Box)] | ||
trait Foo { | ||
fn foo(&self); | ||
} | ||
``` | ||
|
||
Will expand to: | ||
|
||
```rust | ||
impl<'a, T, TAutoImpl> MyTrait<'a, T> for TAutoImpl | ||
where TAutoImpl: ::std::ops::Fn(&T, &'static str) -> Result<(), String> | ||
{ | ||
fn execute<'b>(&'a self, arg1: &'b T, arg1: &'static str) -> Result<(), String> { | ||
self(arg1, arg2) | ||
} | ||
impl Foo for i32 { | ||
fn foo(&self) {} | ||
} | ||
``` | ||
|
||
There are a few restrictions on `#[auto_impl]` for closures. The trait must: | ||
fn requires_foo(_: impl Foo) {} | ||
|
||
- Have a single method | ||
- Have no associated types | ||
- Have no non-static lifetimes in the return type | ||
|
||
## Implement a trait for a borrowed reference | ||
|
||
```rust | ||
#[auto_impl(&, &mut)] | ||
trait MyTrait<'a, T> { | ||
fn execute<'b>(&'a self, arg1: &'b T, arg2: &'static str) -> Result<(), String>; | ||
} | ||
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 | ||
``` | ||
|
||
Will expand to: | ||
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). | ||
|
||
```rust | ||
impl<'auto, 'a, T, TAutoImpl> MyTrait<'a, T> for &'auto TAutoImpl { | ||
fn execute<'b>(&'a self, arg1: &'b T, arg1: &'static str) -> Result<(), String> { | ||
(**self).execute(arg1, arg2) | ||
} | ||
} | ||
|
||
impl<'auto, 'a, T, TAutoImpl> MyTrait<'a, T> for &'auto mut TAutoImpl { | ||
fn execute<'b>(&'a self, arg1: &'b T, arg1: &'static str) -> Result<(), String> { | ||
(**self).execute(arg1, arg2) | ||
} | ||
} | ||
``` | ||
--- | ||
|
||
There are a few restrictions on `#[auto_impl]` for immutably borrowed references. The trait must: | ||
## License | ||
|
||
- Only have methods that take `&self` or have no receiver (static) | ||
Licensed under MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT). | ||
|
||
There are a few restrictions on `#[auto_impl]` for mutably borrowed references. The trait must: | ||
### Contribution | ||
|
||
- Only have methods that take `&self`, `&mut self` or have no receiver (static) | ||
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be licensed as above, without any additional terms or conditions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# 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 | ||
``` |
Oops, something went wrong.