2

The example below is just an example, I know I don't need the Clone for this to work, but if S were an enum with [T] and Vec<T> and I wanted to resize the vector, T would have to be Clone.

struct S<'a, T>{ a: &'a [T] } impl<'a, T> S<'a, T> { pub fn borrow(&self) -> &[T] where [T]: Clone { self.a } } fn main() { let slice:[u8;3] = [1,2,3]; let x = S{a: &slice}; x.borrow(); } 

Playground

Error:

error[E0277]: the trait bound `[u8]: Clone` is not satisfied --> src/main.rs:17:7 | 17 | x.borrow(); | ^^^^^^ the trait `Clone` is not implemented for `[u8]` 

So, why isn't [u8] Clone?

1
  • 5
    [T] is an unsized type, and hence cannot be Cloned (note that Clone::clone returns Self but a [T] cannot live on the stack). A Box<[T]>, however, does implement Clone if T: Clone because it lives on the heap. Commented Jul 1, 2021 at 19:34

2 Answers 2

5

So why isn't [u8] Clone?

Look at the type of the clone method in the definition of Clone:

pub trait Clone { pub fn clone(&self) -> Self; // more stuff omitted.. } 

It returns Self, which would be [u8] in this case. The problem is that [u8] is not Sized, that is, since we don't know how many elements it will have we can't know its size at compile time. But returning it from this method would mean that it is moved onto the stack, which is not possible if the compiler doesn't know how much space to leave for it.

Sign up to request clarification or add additional context in comments.

2 Comments

Would a possible fix be to use const generics and use a templated fixed-size array instead of a slice?
I don't really follow what you are trying to accomplish so it's hard to suggest a "fix". As you say, the example doesn't communicate the problem because Clone is not needed. On the surface, it looks like you need T: Clone not [T]: Clone but you didn't provide enough information to say that with any certainty.
2

I was able to get your code to compile by adding the & to the where clause:

impl<'a, T> S<'a, T> { pub fn borrow(&self) -> &[T] where &'a [T]: Clone, { self.a } } 

The key here being that the slice is the reference to a contiguous set of values: &[u32].

As to why, [u32] does not implement Clone: I believe the reason is that it doesn't have any information as to how many elements are in the range of memory. Whereas the slice type,&[u32], contains a reference to the start of a series of u32 values in memory and how many elements there are. Without the number of elements, cloning the data would be impossible.

3 Comments

Note that &'a [T]: Clone may not lead to desired behavior, as it puts a Clone constraint on the reference type &[T]. Immutable references are always Clone (and Copy) -- &[T] : Clone does not necessarily mean that the slice itself can be cloned.
Example: Calling self.a.clone() in S::borrow does not actually clone the slice or its constituents -- it only clones the reference.
That's a very good point and good to know.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.