Option::cloned disowns mut


#1

I have the code:

#[derive(Clone)]
struct U;

fn main() {
    let u = Some(U);
    Option::cloned(u.as_mut());
}

Which fails with:

Option::cloned(u.as_mut());
               ^^^^^^^^^^ values differ in mutability

https://is.gd/CfASD5

To clone I have to use .map(|t| t.clone()) directly.

Is there any way to use Option::cloned when external method strictly returns Option<&mut T>.

I feel .cloned() has unflexble implementation. Am I right or wrong?


#2

This looks like an oversight to me. Perhaps you could open an issue on github, or even just write up a quick pull request and see what the standard lib team thinks.


#3

Perhaps it should take any Deref type?

impl<T: Clone, U: Deref<Target = T>> Option<U> {
    fn cloned(self) -> Option<T> {
        match self {
            Some(u) => Some(u.clone()),
            None => None,
        }
    }
}

playground

I think this wouldn’t even be a breaking change. However, note that cloned(self) is taken by value, which is normally painless since any Option<&T> implements Copy. That’s harder to deal with for other Deref types.

FWIW, I also tried AsRef<T>, but then T is not constrained in the impl. I think you could move the parameterization onto cloned itself, but this will lean more heavily on type inference at the caller, which could break existing cloned calls.


#4

Thanks for useful ideas! :+1: I think I should to test an alternative implementation as change of standard library. Possible this improvement is worth to be a PR.