Victor Paléologue
Victor Paléologue

Reputation: 2352

Using Cow in a generic struct

The following code:

use std::borrow::Cow;

struct Hip<'a> {
    hip: Cow<'a, [u8]>
}

struct Hop<'a, T: ?Sized + 'a> {
    hop: Cow<'a, T>
}

fn main() {
    let it_be: Hop<[u8]> = [1, 2, 3];
}

Fails to build because "the trait Clone is not implemented for T".

Whereas expecting T to implement Clone (as follows):

struct Hop<'a, T: Clone + ?Sized + 'a> {
    hop: Cow<'a, T>
}

Fails to build because "the trait Clone is not implemented for [u8]".

How come Hip, which is using a [u8], compiles, but not Hop?

Why does the compiler request Clone to be implemented for Hop's T, but not for Hip's [u8]?

On the Rust Playground

Upvotes: 2

Views: 245

Answers (1)

Victor Pal&#233;ologue
Victor Pal&#233;ologue

Reputation: 2352

The documentation says the type should implement ToOwned. The following works:

struct Hop<'a, T: ?Sized + ToOwned> {
    hop: Cow<'a, T>
}

fn main() {
    let it_be: Hop<[u8]> = Hop { hop: Cow::Owned(vec![1, 2, 3]) };
}

About the error message: the compiler generates the implementation of ToOwned for every type implementing Clone. So when the trait ToOwned is missing, it suggests to implement Clone.

This is a mistake because some types have good reasons to implement ToOwnedwithout implementing Clone. [u8] is one of them, hence Hip compiles. Whereas Hop's T was not bound to ToOwned, so it fails.

Upvotes: 3

Related Questions