[Feature request] Add Cloned trait

pub trait Cloned {
    type Output;

    fn cloned(&self) -> Self::Output;
}

impl<'a, T: Clone> Cloned for &'a T {
    type Output = T;

    fn cloned(&self) -> Self::Output {
        (*self).clone()
    }
}

impl<T: Cloned> Cloned for Option<T> {
    type Output = Option<T::Output>;

    fn cloned(&self) -> Self::Output {
        match self {
            Some(v) => Some(v.cloned()),
            None => None,
        }
    }
}

impl<'a, T: Clone> Cloned for Box<T> {
    type Output = T;

    fn cloned(&self) -> Self::Output {
        self.deref().clone()
    }
}

fn foo(a: Option<Option<&i32>>) {
    let b: Option<Option<&i32>> = a.clone();
    let c: Option<Option<i32>> = a.cloned();
}

fn bar(a: Option<Box<i32>>) {
    let b: Option<Box<i32>> = a.clone();
    let c: Option<i32> = a.cloned();
}

ToOwned is not implemented for references and options

Is there anything blocking you from creating a crate with this trait right now?
You could make ToOwned a supertrait.

It's not that clear to me; what's the feature?

  1. If placed in a crate, other crates will not use it

  2. This trait should be implemented for all borrowable types, but I can't

    impl <T, B : Borrow<T>> Cloned for B {
        type Output = T;
    }
    
     error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
    
  3. Not only Cloned

    pub trait Copied {
        type Output;
    
        fn copied(&self) -> Self::Output;
    }
    
    impl<'a, T: Clone + Copy> Copied for &'a T {
        type Output = T;
    
        fn copied(&self) -> Self::Output {
            **self
        }
    }
    
    impl<T: Copied> Copied for Option<T> {
        type Output = Option<T::Output>;
    
        fn copied(&self) -> Self::Output {
            match self {
                Some(v) => Some(v.copied()),
                None => None,
            }
        }
    }
    
  4. This is an abstraction over these cloned
    image

Both the trait and the implementations will have to be put somewhere. Crate's are Rust's compilation units, so they will have to end up in a crate. If you're hoping to see it in the standard library I would advise that in general, code doesn't make its way into the standard library until it's been in use/tested elsewhere.

The first step would be to implement it in a crate.

You might work around it with an implementing struct that has a phantom type. Regardless, how are you proposing this limitation be lifted? Above you were implementing the trait for each borrowable type individually, why not do that?

Not only Cloned? I think you're missing the rest of the sentence. You want more traits?

To do this, I'm pretty sure you'd need Higher Kinded Types (Or associated traits?). Right now, there's no way good way to track which (if any) type constructor (generic type) was used to build the output type.

The uses for the Trait you've described would be a bit more limited.


It might help if you take a moment to describe the generic contexts in which this is useful. Perhaps some examples of this abstraction in use would help as well. Right now, I don't see why you don't just implement this yourself.

The case here is generics, not structs

I can't implement it for other users' types. If it is in the standard library, other users will implement it

Cloned and Copied

users or crates, both have the same meaning

I wrote a utility library

image

If there is this Cloned trait, then TupleCloned can be rewritten as

image

image

There would be no need for separate implementations for & and &mut , and support for other borrowable types at the same time

image image

Other users can implement it from anywhere, right?

They're more likely to implement it if it's in the standard library and commonly used, which is why I've been trying to push you to create a reference implementation and show why/how it could be used.


I'm not seeing how this is helpful yet. Also, you can already implement this. Of course, users of your utilities would need to implement the trait for their types, but that has to happen anyway.


Seems like a good design! Tuples seem pretty under-utilized in Rust, this might help? Still again, it seems like nothing is blocking this from being implemented today.

If it gains traction, then a good case can be made for including it in the standard library.

:slight_smile:


Some of Rust's most used non-std crates define traits that users must implement. Check out Serde, for example.

.cloned() call on Option and Iterator is super useful. But where would you use it generically?

Can it be just a recommended convention to have a method with such name?

3 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.