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 ),*
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.
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 ),+ 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.