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
::
, usingstd
instead ofcore
oralloc
, 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 :
using
self
.
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: ?Sized
fn deref(&self) -> &Self::Target
#[autoimpl(Deref using self.x)]
implements Deref
as follows:
type Target = X
where fieldx
has typeX
fn 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 :
for
Generics ( 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.