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
;
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.
use Display;
use DerivingVia;
;
;
This example is use Deriving Via feature.
B derives Display trait from i32 impl.
use Display;
use DerivingVia;
;
// a new line
;
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
use Display;
use DerivingVia;
;
;
;
Available Derives
;
;
- fmt
Display- requires:
Base: Displayor(via = <Type>) and Type: Display
- requires:
- ops
Eq- requires:
Base: Eqor(via = <Type>) and Type: Eq
- requires:
Ord- requires:
Base: Ordor(via = <Type>) and Type: Ord
- requires:
Add-lile (Add, Sub)- requires:
Base: From<Underlying> - limitations: one hop or
#[transitive]
- requires:
Mul-like (Mul, Div)- requires:
Base: From<Underlying> - limitations: one hop or
#[transitive]
- requires:
Arithmetic(Add, Sub, Mul, Div)- requires:
Base: From<Underlying> - limitations: one hop or
#[transitive]
- requires:
Index- requires:
Base: Indexor(via = <Type>) and Type: Index
- requires:
IndexMut- requires:
Base: IndexMutor(via = <Type>) and Type: IndexMut
- requires:
DerefMut- requires:
Base: DerefMutor(via = <Type>) and Type: DerefMut
- requires:
- hash
Hash- requires:
Base: Hashor(via = <Type>) and Type: Hash
- requires:
- serde
Serialize- requires:
Base: Serializeor(via = <Type>) and Type: Serialize
- requires:
Deserialize- requires:
Base: Deserializeor(via = <Type>) and Type: Deserialize
- requires:
- convert
AsRefAsMutFromIterator- requires:
(via: <ItemType>)
- requires:
IntoIterator- requires:
Base: IntoIteratoror(via: <Type>), Type: IntoIterator
- requires:
Into- requires:
Base: Into<Underlying> - limitations: one hop or
#[transitive]
- requires:
From- limitations: one hop or
#[transitive]
- limitations: one hop or
TryFrom- requires:
Base: From<Underlying> - limitations: one hop or
#[transitive]
- requires:
FromStr- requires:
Base: From<Underlying> - limitations: one hop or
#[transitive]
- requires:
- impls
- Iter
- requires:
Base: IntoIterator and Base dereferenceable to sliceor(via: <Type>), Type: IntoIterator and Type dereferenceable to slice
- requires:
- IntoInner
- requires:
Base: Cloneor(via: <Type>), Type: Clone
- requires:
- Iter
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