dyn_derive 0.3.2

Inherit and derive object-unsafe traits for dynamic Rust.
Documentation
# dyn_derive

Inherit and derive object-unsafe traits for dynamic Rust.

## Introduction

[Object safety](https://doc.rust-lang.org/reference/items/traits.html#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:

```rust compile_fail
// Clone is not object-safe
// PartialEq is not object-safe
pub trait Foo: Clone + PartialEq {
    // This method is not object-safe
    fn adjust(self) -> Self;
}

#[derive(Clone, PartialEq)]
pub struct Bar {
    meta: Box<dyn Foo>,         // The trait `Foo` cannot be made into an object.
}
```

This crate provides a procedural macro for transforming object-unsafe traits into object-safe ones:

```rust
use dyn_derive::*;

#[dyn_trait]
pub trait Foo: Clone + PartialEq {
    fn adjust(self) -> Self;
}

#[derive(Clone, PartialEq)]
pub struct Bar {
    meta: Box<dyn Foo>,         // Now it works!
}
```

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:

```rust
use std::fmt::Debug;
use dyn_derive::*;

#[dyn_trait]
pub trait Foo: Debug + Clone + PartialEq {
    fn answer(&self) -> i32 {
        42
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct MetaImpl;

impl Foo for MetaImpl {}

#[derive(Debug, Clone, PartialEq)]
pub struct Bar {
    meta: Box<dyn Foo>,
}

fn main() {
    let foo1 = Bar { meta: Box::new(MetaImpl) };
    let foo2 = Bar { meta: Box::new(MetaImpl) };
    assert_eq!(foo1, foo2);
    let foo3 = foo1.clone();
    assert_eq!(foo3.meta.answer(), 42);
}
```

### Non-Derivable Traits

Taking the `Add` trait as an example:

```rust
use std::fmt::Debug;
use std::ops::Add;
use dyn_derive::*;

#[dyn_trait]
pub trait Foo: Debug + Add {}

#[derive(Debug)]
pub struct MetaImpl(String);

impl Foo for MetaImpl {}

impl Add for MetaImpl {
    type Output = Self;

    fn add(self, rhs: Self) -> Self {
        Self(self.0 + &rhs.0)
    }
}

pub struct Bar {
    pub meta: Box<dyn Foo>,
}

impl Add for Bar {
    type Output = Self;

    fn add(self, rhs: Self) -> Self {
        Self {
            // `Box<dyn Foo>` can be added!
            meta: self.meta + rhs.meta,
        }
    }
}

fn main() {
    let foo1 = Bar { meta: Box::new(MetaImpl("114".into())) };
    let foo2 = Bar { meta: Box::new(MetaImpl("514".into())) };
    let foo3 = foo1 + foo2;
    println!("{:?}", foo3.meta);    // MetaImpl("114514")
}
```

### Supported Traits

The following std traits are supported:

- `Clone`
- `Neg`, `Not`
- `Add`, `Sub`, `Mul`, `Div`, `Rem`
- `BitAnd`, `BitOr`, `BitXor`, `Shl`, `Shr`
- `AddAssign`, `SubAssign`, `MulAssign`, `DivAssign`, `RemAssign`
- `BitAndAssign`, `BitOrAssign`, `BitXorAssign`, `ShlAssign`, `ShrAssign`
- `PartialEq`, `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`.

```rust
trait Foo: Sized {
  // These are methods.
  fn method_1(&self);
  fn method_2(self) -> Self;
  // These are non-methods.
  fn method_3() -> Option<Vec<Self>>;
  fn method_4(this: &mut Self, that: 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.

```rust
trait FooInstance {
  fn method_1(&self);
  fn method_2(self: Box<Self>) -> Box<dyn FooInstance>;
}

trait FooConstructor {
  fn method_3(&self) -> Option<Vec<Box<dyn FooInstance>>>;
  fn method_4(&self, this: &mut dyn FooInstance, that: Box<dyn FooInstance>);
}
```

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.

```rust ignore
impl FooInstance for ::dyn_std::Instance<Foo> {}
impl FooConstructor for ::dyn_std::Constructor<Foo> {}
```

If you are developing a library, you may write code like this:

```rust ignore
use std::collections::HashMap;
use dyn_std::Constructor;

struct Registry(HashMap<String, Box<dyn FooConstructor>>);

impl Registry {
    fn register<T: Foo>(&mut self, name: impl Into<String>) {
        self.0.insert(name.into(), Box::new(Constructor::<T>::new()));
    }
}
```

And the user of your library may write code like this:

```rust ignore
let mut registry = Registry(HashMap::new());
registry.register::<CustomFooImpl>("custom");
```

## 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]#supported-traits 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 Self`
- `Box<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>` (where `T`, `E` are valid parameter types),
- `&dyn`, `&mut dyn`, `Box<dyn>` of `Fn`, `FnMut`, `FnOnce` (where all the parameters are valid non-referencing parameter types).

The following types are valid parameter types:

```rust ignore
(Self, &Self, Box<Self>)
```
```rust ignore
HashMap<i32, HashMap<i32, &Self>>
```
```rust ignore
Result<Vec<Box<dyn Fn(Self) -> Self>>, Option<Self>>
```

The following types are **NOT** valid parameter types:

```rust ignore
&[Self]
```
```rust ignore
Pin<Arc<Self>>
```
```rust ignore
&dyn Fn(&mut Self)
```

#### 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:

- [as-any]https://github.com/fogti/as-any
- [dyn-clone]https://github.com/dtolnay/dyn-clone
- [partial_eq_dyn]https://github.com/StamesJames/partial_eq_dyn

## License

MIT.