Attribute Macro impl_tools::autoimpl
source · #[autoimpl]Expand description
An alternative to the standard derive macro
#[autoimpl] may be used in two ways:
- On a type definition, to implement a specified trait (like
#[derive]) - On a trait definition, to implement the trait for specified types
supporting
Deref
If using autoimpl and derive macros with Rust < 1.57.0, the
autoimpl attribute must come first (see rust#81119).
On type definitions
| Path | ignore | using | notes |
|---|---|---|---|
::core::borrow::Borrow<T> | - | borrow target | T is type of target field |
::core::borrow::BorrowMut<T> | - | borrow target | T is type of target field |
::core::clone::Clone | yes | - | ignored fields use Default::default() |
::core::cmp::Eq | * | - | *allowed with PartialEq |
::core::cmp::Ord | yes | - | |
::core::cmp::PartialEq | yes | - | |
::core::cmp::PartialOrd | yes | - | |
::core::convert::AsRef<T> | - | ref target | T is type of target field |
::core::convert::AsMut<T> | - | ref target | T is type of target field |
::core::default::Default | - | - | impl_default is a more flexible alternative |
::core::fmt::Debug | yes | - | |
::core::hash::Hash | yes | - | |
::core::marker::Copy | * | - | *allowed with Clone |
::core::ops::Deref | - | deref target | See Deref::Target type below |
::core::ops::DerefMut | - | deref target |
Traits are matched from the path, as follows:
- Only the last component, e.g.
#[autoimpl(Clone)] - The full path with leading
::, e.g.#[autoimpl(::core::clone::Clone)] - The full path without leading
::, e.g.#[autoimpl(core::clone::Clone)] - The full path with/without leading
::, usingstdinstead ofcoreoralloc, e.g.#[autoimpl(std::clone::Clone)]
Ignore: some trait implementations supports ignoring listed fields.
For example, #[autoimpl(PartialEq ignore self.foo)] will implement
PartialEq, comparing all fields except foo.
Note: Copy and Eq do not use ignore, but tolerate its usage by a
companion trait (e.g. #[autoimpl(PartialEq, Eq ignore self.a)]).
Using: some trait implementations require a named field to “use”.
For example, #[autoimpl(Deref using self.foo)] implements Deref to
return a reference to field self.foo.
Parameter syntax
ParamsMulti :
( Trait ),+ Using? Ignores? WhereClause?Using :
usingself.MemberIgnores :
ignore(self.Member ),+WhereClause :
where( WherePredicate ),*
Targets: each Trait listed is implemented for the annotated type.
Generics and where clause
Type generics are inherited from the type definition. Bounds defined by the
type are inherited, but unlike #[derive] no additional bounds for the
trait being implemented are assumed.
A where clause, e.g. where T: Foo, may be used.
A special bound syntax, T: trait, indicates that T must support the
trait being implemented.
Deref::Target type
The Deref trait has two members:
type Target: ?Sizedfn deref(&self) -> &Self::Target
#[autoimpl(Deref using self.x)] implements Deref as follows:
type Target = Xwhere fieldxhas typeXfn deref(&self) -> &Self::Target { &self.x }
For some uses this is fine, but in other cases a different Target type is
preferred. To achieve this, Target may be given explicitly:
#[autoimpl(Deref<Target = T> using self.0)]
struct MyBoxingWrapper<T: ?Sized>(Box<T>);Examples
Implement std::fmt::Debug, ignoring the last field:
#[autoimpl(Debug ignore self.f)]
struct PairWithFn<T> {
x: f32,
y: f32,
f: fn(&T),
}Implement Clone and Debug on a wrapper, with the required bounds:
#[autoimpl(Clone, Debug where T: trait)]
struct Wrapper<T>(pub T);Implement Deref and DerefMut, dereferencing to the given field:
#[autoimpl(Deref, DerefMut using self.1)]
struct AnnotatedWrapper<T>(String, T);On trait definitions
User-defined traits may be implemented over any type supporting Deref
(and if required DerefMut) to another type supporting the trait.
Parameter syntax
ParamsTrait :
forGenerics ( Type ),+ WhereClause?
Targets: the annotated trait is implemented for each Type listed.
Definitive type:
It is required that some generic type parameter has bound trait
(e.g. T: trait). The first such parameter is designated the definitive type.
Trait items
Assuming definitive type T, trait items are implemented as follows:
- associated constant
const C:const C = T::C; - associated type
type X:type X = T::X; - method
fn foo(a: A, b: B):T::foo(a, b) - (unexpanded) macro items: not supported
Generics and where clauses on types and methods are supported.
Items with a where clause with a type bound on Self are not supported
since the item is not guaranteed to exist on the definitive type.
Exception: methods with a default implementation (in this case the item is
skipped).
Examples
Implement MyTrait for &T, &mut T and Box<dyn MyTrait>:
#[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>)]
trait MyTrait {
fn f(&self) -> String;
}The definitive type is T. For example, here, f is implemented with the
body <T as MyTrait>::f(self).
Note further: if the trait uses generic parameters itself, these must be
introduced explicitly in the for<..> parameter list.