Attribute Macro autoimpl

Source
#[autoimpl]
Expand description

An alternative to the standard derive macro

This macro may be used:

§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

Pathignoreusingnotes
::core::borrow::Borrow<T>-borrow targetT is type of target field
::core::borrow::BorrowMut<T>-borrow targetT is type of target field
::core::clone::Cloneyes-ignored fields use Default::default()
::core::cmp::Eq*-*allowed with PartialEq
::core::cmp::Ordyes-
::core::cmp::PartialEqyes-
::core::cmp::PartialOrdyes-
::core::convert::AsRef<T>-ref targetT is type of target field
::core::convert::AsMut<T>-ref targetT is type of target field
::core::default::Default--impl_default is a more flexible alternative
::core::fmt::Debugyes-
::core::hash::Hashyes-
::core::marker::Copy*-*allowed with Clone
::core::ops::Deref-deref targetSee 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 ::, using std instead of core or alloc, e.g. #[autoimpl(std::clone::Clone)]

§Parameter syntax

ParamsMulti :
   ( Trait ),+ Using? Ignores? WhereClause?

Using :
   using self . Member

Ignores :
   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?