How does the std library implement std::borrow::ToOwned for any T: Clone but also specifically for &str?

The std library uses the trait std::borrow::ToOwned to genericalize the Clone trait.

They implement this trait for any T: Clone

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T
where
    T: Clone,
{
    type Owned = T;
    fn to_owned(&self) -> T {
        self.clone()
    }

    fn clone_into(&self, target: &mut T) {
        target.clone_from(self);
    }
}

And also for a number of type specifically - e.g. for &str:


#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl ToOwned for str {
    type Owned = String;

    #[inline]
    fn to_owned(&self) -> String {
        unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
    }

    #[inline]
    fn clone_into(&self, target: &mut String) {
        target.clear();
        target.push_str(self);
    }
}

How do they do this without getting error conflicting implementation for: ...?

E.g. if i do this like:

// #[derive(Clone)]
struct MyStruct;

trait MyTrait {}
impl<T> MyTrait for T where T: Clone {}
impl MyTrait for MyStruct {}

If i uncomment the derive(Clone) i get this error.

There is no impl ToOwned for &str. This impl is for str:

impl ToOwned for str

str is not Clone.

And even if it was Clone it would work, since impl blocks have an implicit Sized bound.
So unless where T: Clone + ?Sized was specified, this world work, too.

And Sized is a fundamental trait, which means coherence can assume the absence of str: Sized means str will never be Sized, so you don't get an "upstream may implement ... In the future" error.

as said above str is not Sized, so an implementation on a generic T with only the bound T : Clone explicitly exclude str.

to reproduce in your own code, you can do


struct MyStruct([()]); // MyStruct is not Sized

trait MyTrait {}
impl<T> MyTrait for T where T: Clone {}
impl MyTrait for MyStruct {}

btw, types that aren't Sized cannot implement Clone, but this would still work if they could.
an example with Debug :

use std::fmt::Debug;
#[derive(Debug)]
struct MyStruct([()]);

trait MyTrait {}
impl<T> MyTrait for T where T: Debug {}
impl MyTrait for MyStruct {}

here MyStruct does implement Debug, but it does not implement Sized, so it is not affected by the blanket impl

interestingly, the following still works, because Sized is a supertrait of Clone

struct MyStruct([()]); // MyStruct is not Sized

trait MyTrait {}
impl<T : ?Sized> MyTrait for T where T: Clone {}
impl MyTrait for MyStruct {}

so the ?Sized is ignored.

but

use std::fmt::Debug;
#[derive(Debug)]
struct MyStruct([()]); // MyStruct is not Sized

trait MyTrait {}
impl<T : ?Sized> MyTrait for T where T: Debug {}
impl MyTrait for MyStruct {} // conflict with the above

does not work because here the blanket impl does cover MyStruct

Clone: Sized anyway, so that doesn’t matter.

Edit: ah, scrolling down, that’s already mentioned.