Skip to content

Commit

Permalink
Better doc for newtype wrappers
Browse files Browse the repository at this point in the history
  • Loading branch information
dhardy committed Nov 17, 2022
1 parent 47f8907 commit 0ffcad9
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 12 deletions.
42 changes: 30 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,16 @@ Unlike [alternatives](#alternatives), `#[autoimpl]` has minimal and intuitive sy
use impl_tools::autoimpl;
use std::fmt::Debug;

#[autoimpl(for<'a, T: trait + ?Sized> Box<T>)]
// Generates: impl<'a, T: Animal + ?Sized> Animal for Box<T> { .. }
// Impl Animal for Box<T> where T: Animal + ?Sized
#[autoimpl(for<T: trait + ?Sized> Box<T>)]
trait Animal {
fn number_of_legs(&self) -> u32;
}

// Impl Debug for Named<T, A: Animal> omitting field animal from output
#[autoimpl(Debug ignore self.animal where T: Debug)]
// Generates: impl<T, A: Animal> std::fmt::Debug for Named<A> where T: Debug { .. }
// Impl Deref and DerefMut to field animal for Named<T, A: Animal>
#[autoimpl(Deref, DerefMut using self.animal)]
// Generates: impl<T, A: Animal> std::ops::Deref for Named<A> { .. }
// Generates: impl<T, A: Animal> std::ops::DerefMut for Named<A> { .. }
struct Named<T, A: Animal> {
name: T,
animal: A,
Expand Down Expand Up @@ -73,20 +72,39 @@ trait allows succinct new-type patterns:

```rust
use impl_tools::autoimpl;
use std::sync::Arc;

#[autoimpl(for<T: trait> &T, &mut T)]
trait Foo {
// Impl Foo for &T, &mut T and Arc<T>
#[autoimpl(for<T: trait + ?Sized> &T, &mut T, Arc<T>)]
// Optional: impl Foo for NewFoo (requires NewFoo: Deref<Target = T>)
#[autoimpl(for<T: trait> NewFoo<T>)]
pub trait Foo {
fn success(&self) -> bool;
}

#[autoimpl(Deref, DerefMut using self.0)]
struct NewFoo<T: Foo>(T);
// Impl Deref and DerefMut to a Target which itself supports Foo
#[autoimpl(Deref<Target = T>, DerefMut using self.0)]
pub struct NewFoo<T: Foo>(T);

// Impl Deref and DerefMut to a Target which itself supports Foo
#[autoimpl(Deref<Target = dyn Foo>, DerefMut using self.0)]
pub struct ArcDynFoo(Arc<dyn Foo>);

#[test]
fn test_foo_newtypes() {
struct Success;
impl Foo for Success {
fn success(&self) -> bool { true }
}

// NewFoo now supports `Deref<Target = T>` and `&T` supports `Foo`.
// Effectively, `NewFoo` supports `Foo`.
// Works for FooRef<'a>(&'a dyn Foo) too; see tests/newtype.rs
// We can now directly call Foo's methods on the wrapper:
assert!(NewFoo(Success).success());
assert!(ArcDynFoo(Arc::new(Success)).success());
}
```

See [`tests/newtype.rs`](https://github.com/kas-gui/impl-tools/blob/master/tests/newtype.rs) for more variants of this pattern.


### Impl Default

Expand Down
2 changes: 2 additions & 0 deletions tests/newtype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ mod inner {
use impl_tools::autoimpl;

#[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>, Rc<T>, Arc<T>)]
// Optionally, we can also implement Foo directly for these types:
// #[autoimpl(for<T: trait> NewFoo<T>, BoxFoo<T>)]
pub trait Foo {
fn is_true(&self) -> bool;
}
Expand Down

0 comments on commit 0ffcad9

Please sign in to comment.