Skip to content

Commit

Permalink
Merge pull request #23 from kas-gui/work
Browse files Browse the repository at this point in the history
Prepare 0.5.0; update README
  • Loading branch information
dhardy authored Sep 22, 2022
2 parents 10d1ae4 + bfc37c8 commit 8a5edc8
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 9 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.5.0] — 2022-09-??
## [0.5.0] — 2022-09-22

- `#[autoimpl]` on traits now merges trait generics with macro generics (#21)
- `lib::autoimpl::struct_items` returns the trait path in addition to impl items (#22)
- Add `lib::autoimpl::ImplArgs::for_fields`, `for_fields_iter` (#22)
- Add autoimpl support for `Copy`, `AsRef`, `AsMut`, `Borrow`, `BorrowMut`,
`PartialEq`, `Eq`, `PartialOrd`, `Ord`, `Hash` (#22)
- Add `#[automatically_derived]` annotation to generated impls (#22)

## [0.4.4] — 2022-09-19

Expand Down
71 changes: 63 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,39 +124,94 @@ Caveat: `rustfmt` won't currently touch the contents. Hopefully that
Extensibility
-------------

Rust's `#[derive]` macro is extensible via `#[proc_macro_derive]` in a `proc-macro` crate. Our macros cannot be extended in the same way, but they can be extended via a new front-end:
Rust's `#[derive]` macro is extensible via `#[proc_macro_derive]` in a `proc-macro` crate.
Our macros cannot be extended in the same way, but they can be extended via a new front-end:

1. Create a copy of the `impl-tools` crate to create a new "front-end" (`proc-macro` crate).
This crate is contains only a little code over the [`impl-tools-lib`] crate.
2. To extend `#[autoimpl]`, write an impl of [`ImplTrait`] and add it to the attribute's definition.
To extend `impl_scope!`, write an impl of [`ScopeAttr`] and add it to the macro's definition.
3. Depend on your new front end crate instead of `impl-tools`.

For an example of this approach, see [kas-macros](https://github.com/kas-gui/kas/tree/master/crates/kas-macros).

[`impl-tools-lib`]: https://docs.rs/impl-tools-lib/
[`ImplTrait`]: https://docs.rs/impl-tools-lib/latest/impl_tools_lib/autoimpl/trait.ImplTrait.html
[`ScopeAttr`]: https://docs.rs/impl-tools-lib/latest/impl_tools_lib/trait.ScopeAttr.html


Supported Rust Versions
------------------------------

The MSRV is 1.56.0 for no particular reason other than that it is the first to support Edition 2021.

When using a sufficiently recent compiler version (presumably 1.65.0), generic associated types
are supported (only applicable to `#[autoimpl]` on trait definitions using GATs).


Alternatives
------------

### Derive alternatives

Both [Educe](https://crates.io/crates/educe) and [Derivative](https://crates.io/crates/derivative)
have similar functionality: the ability to implement various traits with more flexibility than
libstd's `#[derive]`. They also support more functionality such as tweaking the output of `Debug`.
Both have less clean syntax, requiring a minimum of two attributes to do anything, with further
attributes to customise implementations (e.g. to ignore a field).
have similar functionality: the ability to implement standard traits with more flexibility than
libstd's `#[derive]`.

In comparison, impl-tools' `#[autoimpl]` has cleaner syntax but is less flexible:
```rust,ignore
#[derive(Derivative)]
#[derivative(PartialEq, Eq)]
struct Foo<S, T: ?Sized> {
foo: S,
#[derivative(PartialEq="ignore")]
bar: u8,
#[derivative(PartialEq(bound=""), Eq(bound=""))]
ptr: *const T,
}
#[derive(Educe)]
#[educe(PartialEq(bound = "S: PartialEq"), Eq(bound = "S: Eq"))]
struct Foo<S, T: ?Sized> {
foo: S,
#[educe(PartialEq(ignore))]
bar: u8,
ptr: *const T,
}
// impl-tools:
#[autoimpl(PartialEq, Eq ignore self.bar where S: trait)]
struct Foo<S, T: ?Sized> {
foo: S,
bar: u8,
ptr: *const T,
}
```

Note: `#[derive]` and `Derivative` add bounds like `S: PartialEq, T: PartialEq` on generic parameters by default; `Educe` and `impl-tools` do not.

### Derive extensions

[derive_more](https://crates.io/crates/derive_more) isn't exactly an "alternative", simply
supporting `#[derive]` for more standard traits. Possible functionality overlap in the future
(though for now `#[autoimpl]` doesn't support half the traits supported by `#[derive]`).
supporting `#[derive]` for more standard traits such as `Add` and `From`.
This is not (currently) supported by `#[autoimpl]` (or, to my knowledge, any alternative).

[auto_impl](https://crates.io/crates/auto_impl/) allows implementing a trait for reference types
(`&`, `&mut`, `Box`, `Rc`, `Arc`) as well as function types.
(`&`, `&mut`, `Box`, `Rc`, `Arc`) as well as function types. The former (reference types) is
supported by `#[autoimpl]` (and is slightly more general):
```rust,ignore
// auto_impl:
#[auto_impl(&, Box)]
trait Foo {
fn foo(&self);
}
// impl-tools:
#[autoimpl(for<T: trait + ?Sized> &T, Box<T>)]
trait Foo {
fn foo(&self);
}
```


Copyright and Licence
Expand Down
27 changes: 27 additions & 0 deletions tests/autoimpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use impl_tools::autoimpl;

fn test_has_clone(_: impl Clone) {}
fn test_has_copy(_: impl Copy) {}
fn test_has_partial_eq(_foo: impl PartialEq) {}
fn test_has_eq(_foo: impl Eq) {}

#[autoimpl(std::clone::Clone, core::fmt::Debug)]
struct Unit;
Expand Down Expand Up @@ -153,3 +155,28 @@ fn xx_hash_64_0(x: impl core::hash::Hash) -> u64 {
x.hash(&mut hasher);
core::hash::Hasher::finish(&hasher)
}

#[allow(unused)]
#[autoimpl(PartialEq, Eq ignore self.bar where S: trait)]
struct Foo<S, T: ?Sized> {
foo: S,
bar: u8,
ptr: *const T,
}
#[test]
fn foo() {
let x = || 1;
let ptr = &x as *const _;
test_has_partial_eq(Foo {
foo: 1f32,
bar: 0,
ptr,
});
// Expected to fail:
// test_has_eq(Foo { foo: 1f32, bar: 0, ptr });
test_has_eq(Foo {
foo: 1i32,
bar: 0,
ptr,
});
}

0 comments on commit 8a5edc8

Please sign in to comment.