Pre-RFC: `#[derive(From)]` for newtypes

Isn't struct Length(u8) already the de-facto standard for newtype, just that it can require a lot more typing in the derive? Imagine we had a way to "bundle" multiple derives together (I'm not speaking of a derive macro here):

// Or some other syntax, this one potentially even as part of the prelude
// if newtypes are common enough
type NewType = Debug + From + ...;
type Math = Add + Sub + Mul + ...;

// Ideally allow anyone to specify Derive (and trait bound?) collections/bundles,
// Would likely need a different syntax.
type Common = Debug + serde::Serialize + serde::Deserialize;

#[derive(NewType, Math)]
struct Length(u8);

// No Math because it has a different return type
#[derive(NewType)]
struct Instant(u64);

#[derive(Common)]
struct Length{...};

Yes, it's still more than newtype Length = u8, but it's also more flexible and allows specifying what exactly you need.

As for the above mentioned trait bounds: Imagine serde having this:

// In serde (may need to be split between Trait bundle/alias and
// Derive bundle/alias)
type Serde = Serialize + Deserialize;

// In crates using serde
#[derive(Serde)]
struct MyStruct{...}

fn do_something(T: Serde) {...}

Or tokio this:

type Task = Send + Sync + 'static;

// Simplified
pub fn spawn<T: Task>(task: T) {...}

Unless I'm mistaken, this currently requires a third trait with auto-impls if both Serialize and Deserialize are present and would require another proc macro for derive.

5 Likes