auto_impl
A simple compiler plugin for automatically implementing a trait for some common smart pointers and closures.
This library requires the nightly
channel.
Add auto_impl
to your Cargo.toml
:
auto_impl = "*"
Reference in your crate root:
```rust
extern crate auto_impl;
use autoimpl::autoimpl; ```
Add an auto_impl
attribute to traits you want to automatically implement for wrapper types:
```rust
pub trait OrderStoreFilter {
fn filter
Now anywhere that requires a T: OrderStoreFilter
will also accept an &T
or Arc<T>
where T
implements OrderStoreFilter
.
The following types are supported and can be freely combined:
The following types are also supported, but require a blanket implementation (you can only have one of these per trait
):
Box
```rust
trait MyTrait<'a, T>
where T: AsRef
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
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
.
Add the #[auto_impl]
attribute to traits to automatically implement them for wrapper types:
```rust
trait MyTrait<'a, T>
where T: AsRef
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
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
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:
&self
or have no receiver (static)```rust
trait MyTrait<'a, T> { fn execute<'b>(&'a self, arg1: &'b T, arg2: &'static str) -> Result<(), String>; } ```
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)
}
}
There are a few restrictions on #[auto_impl]
for closures. The trait must:
```rust
trait MyTrait<'a, T> { fn execute<'b>(&'a self, arg1: &'b T, arg2: &'static str) -> Result<(), String>; } ```
Will expand to:
```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:
&self
or have no receiver (static)There are a few restrictions on #[auto_impl]
for mutably borrowed references. The trait must:
&self
, &mut self
or have no receiver (static)