A set of helper macros
#[autoimpl]
is a partial replacement for #[derive]
, supporting:
where
clause on generic parametersDeref
by using
a named fieldDebug
may ignore
named fields#[autoimpl]
may also be used on trait definitions to impl for specified types
supporting Deref
.
Unlike alternatives, #[autoimpl]
has minimal and intuitive syntax.
```rust use impl_tools::autoimpl; use std::fmt::Debug;
// Generates: impl<'a, T: Animal + ?Sized> Animal for Box
// Generates: impl
// Generates: impl
fn main() { struct Fish; impl Animal for Fish { fn numberoflegs(&self) -> u32 { 0 } }
let my_fish = Named {
name: "Nemo",
animal: Box::new(Fish),
};
assert_eq!(
format!("{my_fish:?} has {} legs!", my_fish.number_of_legs()),
r#"Named { name: "Nemo", .. } has 0 legs!"#
);
} ```
#[impl_default]
implements std::default::Default
:
```rust use impltools::{impldefault, impl_scope};
enum Tree { Ash, Beech, Birch, Willow }
implscope! { #[impldefault] struct Copse { tree_type: Tree, number: u32 = 7, } } ```
impl_scope!
is a function-like macro used to define a type plus its
implementations. It supports impl Self
syntax:
```rust use impltools::implscope; use std::fmt::Display;
impl_scope! {
/// I don't know why this exists
pub struct NamedThing
// Repeats generic parameters of type
impl Self {
fn format_name(&self) -> String {
format!("{}", self.name)
}
}
// Merges generic parameters of type
impl<O> Self where F: Fn(&str) -> O {
fn invoke(&self) -> O {
(self.func)(&self.format_name())
}
}
} ```
Caveat: rustfmt
won't currently touch the contents. Hopefully that
can be fixed!
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:
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.#[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.impl-tools
.For an example of this approach, see kas-macros.
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).
Both Educe and Derivative
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
struct Foo {
foo: S,
#[derivative(PartialEq="ignore")]
bar: u8,
#[derivative(PartialEq(bound=""), Eq(bound=""))]
ptr: *const T,
}
struct Foo {
foo: S,
#[educe(PartialEq(ignore))]
bar: u8,
ptr: *const T,
}
// impl-tools:
struct Foo {
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_more isn't exactly an "alternative", simply
supporting #[derive]
for more standard traits such as Add
and From
.
This is not (currently) supported by #[autoimpl]
(or, to my knowledge, any alternative).
autoimpl allows implementing a trait for reference 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
// autoimpl:
trait Foo { fn foo(&self); }
// impl-tools:
trait Foo { fn foo(&self); } ```
The COPYRIGHT file includes a list of contributors who claim copyright on this project. This list may be incomplete; new contributors may optionally add themselves to this list.
The impl-tools library is published under the terms of the Apache License, Version 2.0. You may obtain a copy of this licence from the LICENSE file or on the following webpage: https://www.apache.org/licenses/LICENSE-2.0