#[autoimpl]
Expand description
An alternative to the standard derive
macro
This macro may be used:
- On a type definition, to implement a specified trait
- On a trait definition, to implement the trait for specified types
supporting
Deref
§On type definitions
#[autoimpl]
on type definitions functions similarly to #[derive]
. The differences are as follows.
There is no implied bound on generic parameters. Instead, bounds must be specified explicitly, using syntax like where T: Clone
. The special syntax where T: trait
may be used where trait
desugars to the target trait for each implementation. An example:
#[autoimpl(Clone, Debug where T: trait)]
struct Wrapper<T>(pub T);
§ignore
Traits like Debug
may be implemented while ignore
-ing some fields, for example:
#[autoimpl(Debug ignore self.f)]
struct PairWithFn<T> {
x: f32,
y: f32,
f: fn(&T),
}
§using
Traits like Deref
may be implemented by using
a named field, for example:
#[autoimpl(Deref, DerefMut using self.1)]
struct AnnotatedWrapper<T>(String, T);
In the above example, Deref::Target
will be implemented as T
(the type
of the field self.1
). The Target
type may instead be specified explicitly:
#[autoimpl(Deref<Target = T> using self.0)]
struct MyBoxingWrapper<T: ?Sized>(Box<T>);
§Supported traits
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 using 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)]
§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.
§On trait definitions
#[autoimpl]
on trait definitions generates an implementation of that trait
for the given targets. This functions using an implementation of Deref
(and, where required, DerefMut
) to lower the target type to some other
type supporting the trait. We call this latter type the definitive type.
It is required that the target type(s) implemented are generic over some
type parameter(s). These generic parameters are introduced using for<..>
.
It is further required that at least one generic parameter has a bound on
trait
; the first such parameter is inferred to be the definitive type.
For example, the following usage implements MyTrait
for targets &T
,
&mut T
and Box<dyn MyTrait>
using definitive type T
:
#[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>)]
trait MyTrait {
fn f(&self) -> String;
}
The expansion for target Box<T>
looks like:
#[automatically_derived]
impl<T: MyTrait + ?Sized> MyTrait for Box<T> {
fn f(&self) -> String {
<T as MyTrait>::f(self)
}
}
§Generics
Traits using generics and trait items using generics are, for the most part, 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).
An example:
#[autoimpl(for<'a, T> &'a T, &'a mut T, Box<T> where T: trait + ?Sized)]
trait G<V>
where
V: Debug,
{
fn g(&self) -> V;
fn s<X>(&self, f: impl Fn(V) -> X) -> X
where
Self: Sized,
{
f(self.g())
}
}
§Parameter syntax
ParamsTrait :
for
Generics ( Type ),+ WhereClause?