New keyword idea

(note this is my first new feature proposal feedback WOULD be appreciated)

syntax

$vis_quantifier wrapper $new_type_name wraps $type_it_wraps;

purpose

makes it easier to make a 'new type'. While this is a more basic example, in which this new keyword is absolutely NOT necessary, there are in my opinion definitely use cases for this type.

use cases

Lets say your building a emulator backend lib and you have the following enum:

// you can also just interpret the raw bytes but that doesn't matter for this example
pub struct Register {
    id: u8,
}
pub enum Instruction {
    Add(Register, Register),
    Sub(Register, Register),
    ...
}

And after you parsed your bytes into a vector of instructions you want to debug print your instructions, but you don't like the way std's debug implementation looks so you try to define your own:

impl fmt::Debug for Vec<Instruction> {
    ...
}

but then the compiler will complain because of the orphan rules. And you also want to implement some other handy traits. AND you want to use this new type in the execute loop (because you need one of these defined traits). with this keyword it becomes very simple:

pub wrapper InstructionList wraps Vec<Instruction>;

Which expands to the following:

#[repr(transparent)]
pub struct InstructionList(Vec<Instruction>);
impl std::ops::Deref for InstructionList {
    type Target = Vec<Instruction>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl std::ops::DerefMut for InstructionList {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl From<Vec<Instruction>> for InstructionList {
    fn from(v: Vec<Instruction>) -> Self {
        Self(v)
    }
}

when not to use this

  1. if you just need to add extra functions, use an extension trait for this
  2. if the type getting wrapped is public
  3. if you do not want to implement DerefMut, or one of the other traits auto implemented

So what do you all think? Is this used often enough to make a keyword out of it?

You can do this today with derive_more:

use derive_more::{Deref, DerefMut, From};

#[derive(Deref, DerefMut, From)]
#[repr(transparent)]
pub struct InstructionList(Vec<Instruction>);

For the reduction of boilerplate, I think it would be better to incorporate these derive macros into the standard library, than to add a new distinct item syntax that has a specific set of derives built in.

2 Likes

That’s an even better idea! Isn’t there already an experimental From derive? And how would we add the other to std? Do I still need to submit an RFC for that?

And idk if this is possible, but if you would have a struct with only one item, wouldn’t it be possible to just derive whichever traits that one item implements? Don’t think this is possible though…

Apparently so. I did not remember.

And how would we add the other to std? Do I still need to submit an RFC for that?

However, there has probably been lots of previous discussion of derive(Deref) (I don't have links handy) and you should definitely review it before posting a new ACP.

It’s not possible, because for arbitrary traits, it’s not possible to automatically tell which types the wrapper should be substituted for in the inner trait impl.

1 Like