dyn_derive
Inherit and derive object-unsafe traits for dynamic Rust.
Introduction
Object safety is a property of traits in Rust that determines whether the trait can be used as a trait object. However, the requirement for object safety is quite strict, limiting the expressiveness of the type system.
For example, you cannot simply write:
// Clone is not object-safe
// PartialEq is not object-safe
This crate provides a procedural macro for transforming object-unsafe traits into object-safe ones:
use *;
Although there are still some limitations, this technique works smoothly in my scenarios.
Supertraits
Supertraits is also required to be object-safe if the trait needs to be used as a trait object. However, many useful traits are not object-safe, such as Clone and PartialEq.
To tackle this issue, this crate transforms the supertraits into object-safe ones, so that they can be used as supertraits and be derived for your custom types.
Basic Example
Below is a basic example of how to use this crate:
use Debug;
use *;
;
Non-Derivable Traits
Taking the Add trait as an example:
use Debug;
use Add;
use *;
;
Supported Traits
The following std traits are supported:
CloneNeg,NotAdd,Sub,Mul,Div,RemBitAnd,BitOr,BitXor,Shl,ShrAddAssign,SubAssign,MulAssign,DivAssign,RemAssignBitAndAssign,BitOrAssign,BitXorAssign,ShlAssign,ShrAssignPartialEq,Eq,PartialOrd,Ord
More std traits and custom traits may be supported in the future.
Methods
Note: This part is not yet complete.
In Rust, associate functions can be divided into two types: methods and non-methods, depending on whether their first parameter is named self.
This crate supports both methods and non-methods, but they are treated differently. Methods and non-methods are separated into two traits, namely instance and constructor. They are both object-safe.
The original Foo trait (which may or may not be object-safe) can be wrapped by Instance and Constructor types in order to be used as an instance or constructor.
If you are developing a library, you may write code like this:
use HashMap;
use Constructor;
;
And the user of your library may write code like this:
let mut registry = Registry;
registry.;
Specification
A trait should satisfy the all following requirements to be transformed into an object-safe trait by the #[dyn_trait] attribute.
Supertraits
All supertraits must be:
- either object-safe,
- or one of the above std traits.
Sized will be automatically removed from the supertraits for instance and constructor traits, but retained for the original trait.
Associated Constants
It must not have any associated constants.
Associated Types
It must not have any associated types with generics.
Associated Functions
Receiver Types
Receiver types are types that can be used as the receiver of a method call. The following types can be used as receiver types:
Self&Self&mut SelfBox<Self>
Note that Rc<Self>, Arc<Self>, and Pin<P> (where P is receiver) are not currently supported.
Parameters Types
All the parameters must be of the following types:
- types that does not contain
Self, - receiver types,
- tuples of valid parameter types,
- monads such as
Option<T>,Result<T, E>,Vec<T>(whereT,Eare valid parameter types), &dyn,&mut dyn,Box<dyn>ofFn,FnMut,FnOnce(where all the parameters are valid non-referencing parameter types).
The following types are valid parameter types:
The following types are NOT valid parameter types:
&
&dyn Fn
Return Types
The return type must be a non-referencing parameter type.
Generics
Not have any type parameters (although lifetime parameters are allowed).
impl Trait is considered as a type parameter, thus it is not allowed.
Credits
The crate is inspired by the following crates:
License
MIT.