Matrix Test crate-name at crates.io

crate-name at docs.rs

This library is a slightly more convenient version of derive for newtype pattern. The library provides features such as Generalised Newtype Deriving, which allows methods of the base type of newtype to be invoked by transitive application of Deref traits. It also allows derives to be generated based on a specific base implementation using the Deriving Via feature. => See also Generalised derived instances for newtypes and Deriving via.

The Rust Reference says:

Deref should only be implemented for smart pointers to avoid confusion.

However, this is the only way to do it, as there is no mechanism such as Generalised Newtype Deriving available. I consider it acceptable to use Deref for the newtype pattern. Please use this library if and only if you agree with this idea.

Generalised Newtype Deriving by Deref trait

The DerivingVia macro generates the Deref trait. Therefore, repeatedly dereferencing the receiver-type even if the method call is directly ineligible as a syntax. In other words, if the type derives DerivingVia, it can be treated as an UNDERLING TYPE. This works for method calls in general. This is similar to what smart pointers do. Types that derive DerivingVia will behave as Smart Wrappers.

Example

```rust

[derive(DerivingVia)]

pub struct Foo(i32);

fn main() { let foo = Foo(42);

// This works because of Deref trait. // ToOwned trait is implemented for i32. // Foo is dereferenced to i32 and toowned for i32 is called. let i: i32 = foo.toowned(); } ```

Foo desn't implement ToOwned trait, but i32 implements ToOwned trait. foo.to_owned() will deref if it doesn't work directly. foo is dereferenced to i32 and to_owned() is called for i32.

Deriving Via

Using the deriving via feature, it is possible to generate derives from the impl of a specific base of a multi-layered wrapped type.

Example

This example is not use Deriving Via feature.

```rust use std::fmt::Display;

use deriving_via::DerivingVia;

[derive(DerivingVia)]

pub struct A(i32);

impl Display for A { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "A({})", self.0) } }

[derive(DerivingVia)]

pub struct B(A);

fn main() { let b = B(A(42));

// b.to_string() uses A::Display impl (most nearest impl). asserteq!(b.tostring(), "A(42)"); } ```

This example is use Deriving Via feature. B derives Display trait from i32 impl.

```rust use std::fmt::Display;

use deriving_via::DerivingVia;

[derive(DerivingVia)]

pub struct A(i32);

impl Display for A { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "A({})", self.0) } }

[derive(DerivingVia)]

[deriving(Display(via: i32))] // a new line

pub struct B(A);

fn main() { let b = B(A(42));

// b.to_string() uses B::Display impl directly. asserteq!(b.tostring(), "42"); } ```

transitive attribute

Deref trait works transitive, but how we re-constructs a Self type? Unfortunately, no convenience mechanism exists in the language, so it is necessary to teach how to revert using the #[transitive] attribute. Some trait require #[transitive] attribute (see Available Derives section).

Example

```rust use std::fmt::Display;

use deriving_via::DerivingVia;

[derive(DerivingVia)]

[deriving(From)]

pub struct A(i32);

[derive(DerivingVia)]

[deriving(From)]

pub struct B(A);

[derive(DerivingVia)]

[deriving(From, Add(via: i32), Display(via: i32))]

[transitive(i32 -> A -> B -> C)]

pub struct C(B);

fn main() { let c: C = C(B(A(42))) + C(B(A(42))); println!("{c}"); } ```

Available Derives

```rust struct Base(Underlying);

[derive(DerivingVia)]

[deriving()]

struct Target(Base); ```

Caveat

DerivingVia using transitive case of Type Coercion. According to rumours, transitive Type Coercion is not fully supported yet.

See: https://doc.rust-lang.org/reference/type-coercions.html#coercion-types