Attribute Macro impl_tools::autoimpl
source · [−]#[autoimpl]Expand description
A variant of 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 re-implement that trait for a specified type
supporting
Deref
If using autoimpl and derive macros with Rust < 1.57.0, the
autoimpl attribute must come first (see rust#81119).
Trait implementation
| Name | Path | ignore | using |
|---|---|---|---|
Clone | ::std::clone::Clone | initialized with Default::default() | - |
Debug | ::std::fmt::Debug | field is not printed | - |
Default | ::std::default::Default | - | - |
Deref | ::std::ops::Deref | - | deref target |
DerefMut | ::std::ops::DerefMut | - | deref target |
Note: impl_default is a more flexible alternative to Default.
Ignore: trait supports ignoring fields (e.g. #[autoimpl(Debug ignore self.foo)]).
Using: trait requires a named field to “use”. Example:
#[autoimpl(Deref using self.foo)] implements Deref to return (a
reference to) field self.foo.
Traits are matched according to the path, via one of three forms:
- Only the last component, e.g.
#[autoimpl(Clone)] - The full path except leading
::, e.g.#[autoimpl(std::clone::Clone)] - The full path with leading
::, e.g.#[autoimpl(::std::clone::Clone)]
Note regarding no_std usage: the above table is wrong in that traits use
paths in core or alloc, but also match std. That is,
#[autoimpl(std::clone::Clone)] and #[autoimpl(core::clone::Clone)] are
equivalent and generate an impl for ::core::clone::Clone.
Parameter syntax
ParamsMulti :
( Trait ),+ Using? Ignores? WhereClause?Using :
usingself.MemberIgnores :
ignore(self.Member ),+WhereClause :
where( WherePredicate ),*
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.
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);Trait re-implementation
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 ),+ Definitive? WhereClause?Generics :
<( GenericParam )>Definitive :
usingType
Examples
Implement MyTrait for &T, &mut T and Box<dyn MyTrait>:
#[autoimpl(for<'a, T: trait + ?Sized> &'a T, &'a mut T, Box<T>)]
trait MyTrait {
fn f(&self) -> String;
}Note that the first parameter bound like T: trait is used as the
definitive type (required). 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.