#traits #terms #pattern #macro #binary-operator

trait-tactics

Macros that provide common patterns for implementing traits in terms of other traits

1 unstable release

0.1.0 Apr 7, 2024

#1492 in Rust patterns

Download history 107/week @ 2024-04-05 14/week @ 2024-04-12

121 downloads per month
Used in flexint

MIT license

11KB

Macros that provide common patterns for implementing traits in terms of other traits.


lib.rs:

Macros that provide common patterns for implementing traits in terms of other traits.

Binary operators

A binary operator trait is a trait that has:

  • A single generic type argument representing the right-hand-side operand, commonly defaulted to Self
  • A single associated type Output
  • A single method whose two arguments are self and the right-hand-side operand, returning Self::Output

A compound assignment operator trait is a trait that has:

  • A single generic type argument representing the right-hand-side operand, commonly defaulted to Self
  • A single method whose two arguments are &mut self and the right-hand-side operand, returning ()

Particularly when overloading one of Rust's built-in binary operators, it is customary to provide implementations not only for A ⋄ B, but also for &A ⋄ B, A ⋄ &B, and &A ⋄ &B (where stands for the operator to be overloaded, and A and B are operand types). Furthermore, if the binary operator has a corresponding compound assignment operator (which we will refer to as =), it is customary to provide implements for A ⋄= B and A ⋄= &B. The macros provided by this module assist in writing these additional trait implementations.

First, implement &A ⋄ &B. This is the most general implementation, as all other implementations can be written in terms of it.

Then, provide the implementations suggested below, either by using the appropriate macro, or by explicitly writing an optimized implementation.

  • If the binary operator has a corresponding compound assignment operator:
    1. Implement A ⋄= &B in terms of &A ⋄ &B using [assign_via_binop_ref_lhs].
    2. Implement A ⋄= B in terms of A ⋄= &B using [assign_via_assign_ref].
    3. Implement A ⋄ &B in terms of A ⋄= &B using [binop_via_assign].
    4. Implement &A ⋄ B in terms of &A ⋄ &B using [binop_via_binop_ref_rhs].
    5. Implement A ⋄ B in terms of A ⋄= B using [binop_via_assign].
  • Otherwise:
    1. Implement A ⋄ &B in terms of &A ⋄ &B using [binop_via_binop_ref_lhs].
    2. Implement &A ⋄ B in terms of &A ⋄ &B using [binop_via_binop_ref_rhs].
    3. Implement A ⋄ B in one of two ways:
      • in terms of &A ⋄ B using [binop_via_binop_ref_lhs], or
      • in terms of A ⋄ &B using [binop_via_binop_ref_rhs] (preferred when A ⋄ &B is an optimized implementation).

Dependencies

~0.7–1.2MB
~27K SLoC