Skip to content

Commit 344f294

Browse files
committed
tidy up implementation
1 parent da1ccdb commit 344f294

File tree

13 files changed

+376
-120
lines changed

13 files changed

+376
-120
lines changed

Cargo.toml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
[workspace]
2-
members = [
3-
"auto_impl",
4-
"auto_impl_internals"
5-
]
1+
[package]
2+
name = "auto_impl"
3+
version = "0.1.0"
4+
authors = ["Ashley Mannix <[email protected]>"]
5+
6+
[lib]
7+
proc-macro = true
8+
9+
[dependencies]
10+
quote = "*"
11+
syn = { version = "*", features = ["full"] }

README.md

Lines changed: 129 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,131 @@
11
# `auto_impl`
22

3-
This library is a simple compiler plugin for automatically implementing a trait for some common wrapper types.
3+
This library is a simple compiler plugin for automatically implementing a trait for some common smart pointers and closures.
4+
5+
# Usage
6+
7+
This library requires the `nightly` channel.
8+
9+
Add `auto_impl` to your `Cargo.toml`:
10+
11+
```
12+
auto_impl = "*"
13+
```
14+
15+
Reference in your crate root:
16+
17+
```rust
18+
#![feature(proc_macro)]
19+
20+
extern crate auto_impl;
21+
22+
use auto_impl::auto_impl;
23+
```
24+
25+
The following types are supported:
26+
27+
- [`Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html)
28+
- [`Rc`](https://doc.rust-lang.org/std/rc/struct.Rc.html)
29+
- [`Box`](https://doc.rust-lang.org/std/boxed/struct.Box.html)
30+
- [`Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html)
31+
- [`FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html)
32+
- [`FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html)
33+
34+
## Implement a trait for a smart pointer
35+
36+
Add the `#[auto_impl]` attribute to traits to automatically implement them for wrapper types:
37+
38+
```rust
39+
#[auto_impl(Arc, Box, Rc)]
40+
trait MyTrait<'a, T>
41+
where T: AsRef<str>
42+
{
43+
type Type1;
44+
type Type2;
45+
46+
fn execute1<'b>(&'a self, arg1: &'b T) -> Result<Self::Type1, String>;
47+
fn execute2(&self) -> Self::Type2;
48+
}
49+
```
50+
51+
Will expand to:
52+
53+
```rust
54+
impl<'a, T, TAutoImpl> MyTrait<'a, T> for ::std::sync::Arc<TAutoImpl>
55+
where TAutoImpl: MyTrait<'a, T>,
56+
T: AsRef<str>
57+
{
58+
type Type1 = TAutoImpl::Type1;
59+
type Type2 = TAutoImpl::Type2;
60+
61+
fn execute1<'b>(&'a self, arg1: &'b T) -> Result<Self::Type1, String> {
62+
self.as_ref().execute1(arg1)
63+
}
64+
65+
fn execute2(&self) -> Self::Type2 {
66+
self.as_ref().execute2()
67+
}
68+
}
69+
70+
impl<'a, T, TAutoImpl> MyTrait<'a, T> for Box<TAutoImpl>
71+
where TAutoImpl: MyTrait<'a, T>,
72+
T: AsRef<str>
73+
{
74+
type Type1 = TAutoImpl::Type1;
75+
type Type2 = TAutoImpl::Type2;
76+
77+
fn execute1<'b>(&'a self, arg1: &'b T) -> Result<Self::Type1, String> {
78+
self.as_ref().execute1(arg1)
79+
}
80+
81+
fn execute2(&self) -> Self::Type2 {
82+
self.as_ref().execute2()
83+
}
84+
}
85+
86+
impl<'a, T, TAutoImpl> MyTrait<'a, T> for ::std::rc::Rc<TAutoImpl>
87+
where TAutoImpl: MyTrait<'a, T>,
88+
T: AsRef<str>
89+
{
90+
type Type1 = TAutoImpl::Type1;
91+
type Type2 = TAutoImpl::Type2;
92+
93+
fn execute1<'b>(&'a self, arg1: &'b T) -> Result<Self::Type1, String> {
94+
self.as_ref().execute1(arg1)
95+
}
96+
97+
fn execute2(&self) -> Self::Type2 {
98+
self.as_ref().execute2()
99+
}
100+
}
101+
```
102+
103+
There are a few restrictions on `#[auto_impl]` for smart pointers. The trait must:
104+
105+
- Only have methods that take `&self`
106+
107+
## Implement a trait for a closure
108+
109+
```rust
110+
trait FnTrait2<'a, T> {
111+
fn execute<'b>(&'a self, arg1: &'b T, arg2: &'static str) -> Result<(), String>;
112+
}
113+
```
114+
115+
Will expand to:
116+
117+
```rust
118+
impl<'a, T, TFn> FnTrait2<'a, T> for TFn
119+
where TFn: Fn(&T, &'static str) -> Result<(), String>
120+
{
121+
fn execute<'b>(&'a self, arg1: &'b T, arg1: &'static str) -> Result<(), String> {
122+
self(arg1, arg2)
123+
}
124+
}
125+
```
126+
127+
There are a few restrictions on `#[auto_impl]` for closures. The trait must:
128+
129+
- Have a single method
130+
- Have no associated types
131+
- Have no non-static lifetimes in the return type

auto_impl/Cargo.toml

Lines changed: 0 additions & 11 deletions
This file was deleted.

auto_impl/src/lib.rs

Lines changed: 0 additions & 31 deletions
This file was deleted.

auto_impl_internals/src/impl_fn.rs

Lines changed: 0 additions & 58 deletions
This file was deleted.

compile_test/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/target/
2+
**/*.rs.bk
3+
Cargo.lock
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
[package]
2-
name = "auto_impl_internals"
2+
name = "auto_impl_compile_test"
33
version = "0.1.0"
44
authors = ["Ashley Mannix <[email protected]>"]
55

66
[dependencies]
7-
quote = "*"
8-
syn = { version = "*", features = ["full"] }
7+
auto_impl = { version = "*", path = "../" }

compile_test/src/main.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#![feature(proc_macro)]
2+
3+
extern crate auto_impl;
4+
5+
use auto_impl::auto_impl;
6+
7+
#[auto_impl(Fn)]
8+
trait FnTrait1 {
9+
fn execute(&self);
10+
}
11+
12+
#[auto_impl(Fn)]
13+
trait FnTrait2<'a, T> {
14+
fn execute<'b, 'c>(&'a self, arg1: &'b T, arg2: &'c T, arg3: &'static str) -> Result<T, String>;
15+
}
16+
17+
#[auto_impl(FnMut)]
18+
trait FnTrait3 {
19+
fn execute(&mut self);
20+
}
21+
22+
#[auto_impl(Arc, Box, Rc)]
23+
trait RefTrait1<'a, T: for<'b> Into<&'b str>> {
24+
type Type1;
25+
type Type2;
26+
27+
fn execute1<'b>(&'a self, arg1: &'b T) -> Result<Self::Type1, String>;
28+
fn execute2(&self) -> Self::Type2;
29+
}
30+
31+
fn main() {
32+
println!("Hello, world!");
33+
}
File renamed without changes.

0 commit comments

Comments
 (0)