20 unstable releases (8 breaking)

0.10.0 Sep 8, 2023
0.9.0 Jun 29, 2023
0.8.0 Feb 7, 2023
0.6.2 Dec 16, 2022
0.3.0 Mar 31, 2022

#82 in Procedural macros

Download history 1181/week @ 2024-01-22 1144/week @ 2024-01-29 1204/week @ 2024-02-05 1296/week @ 2024-02-12 1116/week @ 2024-02-19 1056/week @ 2024-02-26 1381/week @ 2024-03-04 1604/week @ 2024-03-11 2050/week @ 2024-03-18 2146/week @ 2024-03-25 2882/week @ 2024-04-01 2828/week @ 2024-04-08 2954/week @ 2024-04-15 2634/week @ 2024-04-22 1855/week @ 2024-04-29 2250/week @ 2024-05-06

9,777 downloads per month
Used in 47 crates (11 directly)




Test Status Latest version API Minimum rustc version

A set of helper macros



#[autoimpl] is a partial replacement for #[derive], supporting:

  • Explicit where clause on generic parameters
  • No implicit bounds on generic parameters beyond those required by the type
  • Traits like Deref by using a named field
  • Traits like Debug 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.

use impl_tools::autoimpl;
use std::fmt::Debug;

// 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)]
// Impl Deref and DerefMut to field animal for Named<T, A: Animal>
#[autoimpl(Deref, DerefMut using self.animal)]
struct Named<T, A: Animal> {
    name: T,
    animal: A,

fn main() {
    struct Fish;
    impl Animal for Fish {
        fn number_of_legs(&self) -> u32 {

    let my_fish = Named {
        name: "Nemo",
        animal: Box::new(Fish),

        format!("{my_fish:?} has {} legs!", my_fish.number_of_legs()),
        r#"Named { name: "Nemo", .. } has 0 legs!"#

New-type wrappers

A combination of Deref on the new-type and trait-reimplementation on the trait allows succinct new-type patterns:

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

// 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;

// 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>);

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

    // We can now directly call Foo's methods on the wrapper:

See tests/newtype.rs for more variants of this pattern.

Impl Default

#[impl_default] implements std::default::Default:

enum Tree { Ash, Beech, Birch, Willow }

impl_tools::impl_scope! {
    struct Copse {
        tree_type: Tree,
        number: u32 = 7,

Note: #[impl_default] is matched within an impl_scope! regardless of imports.

Impl Scope

impl_scope! is a function-like macro used to define a type plus its implementations. It supports impl Self syntax:

use std::fmt::Display;

impl_tools::impl_scope! {
    /// I don't know why this exists
    pub struct NamedThing<T: Display, F> {
        name: T,
        func: F,

    // 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 {

Caveat: rustfmt won't currently touch the contents. Hopefully that can be fixed!

Impl Anon

impl_anon! is a function-like macro to construct a single-use struct with custom implementations (similar: RFC#2604).


use std::fmt;
fn main() {
    let world = "world";
    let says_hello_world = impl_tools::impl_anon! {
        struct(&'static str = world);
        impl fmt::Display for Self {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "hello {}", self.0)
    assert_eq!(format!("{}", says_hello_world), "hello world");


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.

Supported Rust Versions

The MSRV is 1.58.0.

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).


Derive alternatives

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:

#[derivative(PartialEq, Eq)]
struct Foo<S, T: ?Sized> {
    foo: S,
    bar: u8,
    #[derivative(PartialEq(bound=""), Eq(bound=""))]
    ptr: *const T,

#[educe(PartialEq(bound = "S: PartialEq"), Eq(bound = "S: Eq"))]
struct Foo<S, T: ?Sized> {
    foo: S,
    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 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).

auto_impl 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):

// 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);

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


~21K SLoC