Trait condition on struct, is there a use case for it?

Hi, I was thinking... is there any use to set a trait condition on a struct or out of a function/impl block?

As example:

struct P<T> {
    x: T,
}

impl<T: Clone> P<T> {
    fn clone2(&self) -> Self {
        P { x: self.x.clone() }
    }
}

Any function we create, that could need a trait condition like the clone2 function, is enough to set the condition on the impl block, actually even put a condition on the struct definition, does not means the T on the impl block will inherit the condition, you still need to write the same condition, just to write it explicitly, this will not works:

struct P<T: Clone> {
    x: T,
}

impl<T> P<T> {
    fn clone2(&self) -> Self {
        P { x: self.x.clone() }
    }
}

By the way I do not understand why in the impl black, P is not restricted to the struct definition, seems weird, still is on the side of the question.

Is there any useful case where the condition is used on the struct declaration and not in the impl block?

Also force a trait on the struct, would force use to use that condition on the impl block too, but seems not useful at all, because without it, we still would get an error to declare in the impl T with Clone.

Thx!

Sometimes you may want to refer to associated types of the trait:

struct ItemOfAnIterator<I: Iterator> {
   item: I::Item
}
4 Likes

If you use the trait in Drop impl it also has to be on the struct.

4 Likes

You can also avoid it by adding more generic parameters.

For example, we could replace

pub enum Cow<'a, B: ?Sized + 'a>
where
    B: ToOwned,
{
    /// Borrowed data.
    Borrowed(&'a B),

    /// Owned data.
    Owned( <B as ToOwned>::Owned),
}

with

pub enum Cow<'a, B: ?Sized + 'a, O = <B as ToOwned>::Owned>
{
    /// Borrowed data.
    Borrowed(&'a B),

    /// Owned data.
    Owned(O),
}

And then just where O: Borrow<B> where you need it.

That doesn't really remove the trait from the enum definition. You could do a plain Cow<B, O> without mentioning any traits at the definition site, but that then requires using two parameters down the stream, so it's not Cow<str> any more, but Cow<str, String>.

1 Like

Well, it depends how you use it. It means that you have the choice of

  1. Just use Cow<B> with a where T: ToOwned bound, or
  2. Use Cow<B, O> in full generality without needing a where (unless you need it in the body).