Impl-tools
A set of helper macros
Macros
Autoimpl
#[autoimpl] is a partial replacement for #[derive], supporting:
- Explicit
whereclause on generic parameters - No implicit bounds on generic parameters beyond those required by the type
- Traits like
Derefbyusinga named field - Traits like
Debugmayignorenamed 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 autoimpl;
use Debug;
// Impl Animal for Box<T> where T: Animal + ?Sized
// Impl Debug for Named<T, A: Animal> omitting field animal from output
// Impl Deref and DerefMut to field animal for Named<T, A: Animal>
New-type wrappers
A combination of Deref on the new-type and trait-reimplementation on the
trait allows succinct new-type patterns:
use autoimpl;
use Arc;
// Impl Foo for &T, &mut T and Arc<T>
// Optional: impl Foo for NewFoo (requires NewFoo: Deref<Target = T>)
// Impl Deref and DerefMut to a Target which itself supports Foo
;
// Impl Deref and DerefMut to a Target which itself supports Foo
;
See tests/newtype.rs for more variants of this pattern.
Impl Default
#[impl_default] implements std::default::Default:
impl_scope!
Note: #[impl_default] is matched within an impl_scope! regardless of imports.
Impl Self
#[impl_self] provides impl Self syntax, avoiding the
need to repeat generics when writing impls on a local type definition.
This supercedes impl_scope! (except regarding macro@impl_default).
use Display;
Note that struct NamedThing is defined directly within the outer namespace,
not within the mod NamedThing. This is a hack required to ensure the contents
use valid Rust syntax and are thus formattable using cargo fmt.
Impl Anon
impl_anon! is a function-like macro to construct a single-use struct with
custom implementations (similar: RFC#2604).
Example:
use fmt;
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:
- Create a copy of the
impl-toolscrate to create a new "front-end" (proc-macrocrate). This crate is contains only a little code over theimpl-tools-libcrate. - To extend
#[autoimpl], write an impl ofImplTraitand add it to the attribute's definition. To extend#[impl_self], write an impl ofScopeAttrand add it to the macro's definition. - Depend on your new front end crate instead of
impl-tools.
For an example of this approach, see kas-macros.
Alternatives
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:
// impl-tools:
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:
// impl-tools:
derive-where is a variant of the
standard #[derive] macro supporting custom generic bounds.
(This offers a subset of the functionality of #[autoimpl]).
Copyright and Licence
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