AsBox trait, trait template parameters


#1

I’m trying to implement an AsBox<T> trait such that functions requiring a boxed argument can also accept an owned value automatically.

Where T is a concrete type it works fine: playpen example

However, where T is a trait (which is the real reason for our function to accept a box, not an owned value), I can’t get it to work. Is there any way to say that a template parameter is a trait?
playpen


#2

@dhardy There are a few limitations here:

  1. There is no Trait trait implemented by all trait object types, so T: Trait is right out.
  2. Even if there were, T would then be the raw trait object type associated with a given trait, not the trait itself, so S: T would not be valid syntax.

So you just can’t write this as a general impl rule for all trait objects. You can write this, specific to a given trait:

impl<'a, S> AsBox<fmt::Display + 'a> for Box<S> where S: fmt::Display + 'a {
    fn as_box(self) -> Box<fmt::Display + 'a> { box *self }
}

Now, let’s do the same thing for the final impl:

impl<'a, S> AsBox<fmt::Display + 'a> for S where S: fmt::Display + 'a {
    fn as_box(self) -> Box<fmt::Display + 'a> { box self }
}

Once we’ve done this, we get conflicting impl errors. It turns out that this impl actually encompasses both Box<Display> and Box<S> where S: fmt::Display. You only need the one. Unfortunately, it reallocates the underlying trait object if you’re passing a trait object. You can avoid this with specialization if its important to you.

This gives you what you want, but on a trait-by-trait basis. You could easily write a macro like as_boxed_trait!(Display); to provide the impls that for each trait you want with less copy-pasting.