Search code examples
rusttraitsprimitive

How can str be copied if it doesn't implement the Copy trait?


"The str type, also called a 'string slice', is the most primitive [emphasis added] string type." (https://doc.rust-lang.org/std/primitive.str.html)

Intuitively str should therefore be copiable, which it is:

fn main() {
    let _str = "hello";
    let _str2 = _str;

    println!("{}", _str); // Output: hello
}

However, it does not implement the Copy trait:

fn main() {
    is_copy::<str>(); // Compile time error: the trait std::marker::Copy is not implemented for str
}

fn is_copy<T: Copy>() {}

What allows this copy-like behaviour with str?


Solution

  • "abc" is more than just a str. It is in fact a reference:

    fn name_of_val<T>(_: T) {
        println!("{:?}", std::any::type_name::<T>());
    }
    name_of_val("abc");
    //Prints "&str".
    

    Playground.

    Therefore, we can't look at the str implementations directly, instead we must look at the &T (Reference) implementations of traits.

    We have a copy impl:

    impl<'_, T> Copy for &'_ T
    where
        T: ?Sized;
    

    This satisfies &str. But since str is unsized, we cannot impl copy for it, since it is the data in a string, not a pointer/reference/(size, ptr) to it. We could therefore not do a bitwise Copy of the str since we wouldn't know how much data to copy.