Search code examples
rustborrow-checkerownership

How Option<&T> implement Copy


I noticed something weird about the map function of Option<&T> and Option<T>, after a quick googling, there is someone else noticed the same issue, as described in this question. I will just use the same example.

let greet: Option<String> = Some("hi".to_string());

let mapped = greet.map(|e|e);

dbg!(mapped);
dbg!(greet);

the error message is :

use of moved value: `greet` ....

on the other hand, the following code is ok.

let greet: Option<String> = Some("hi".to_string());

let mapped = greet.as_ref().map(|e|e);

dbg!(mapped);
dbg!(greet);

the type of map function is:

pub const fn map<U, F>(self, f: F) -> Option<U>

So the ownership of the caller should be transferred to the `self' in map, and the explanation from that question is "Option<&T> implements Copy".

therefore, Option<T> transfers the ownership thus cause the error, while Option<&T> just create a new copy.

However, I cannot find anywhere that shows "Option<&T> implements Copy", the worse thing is this, from the document :

/// The `Option` type. See [the module level documentation](self) for more.
#[derive(Copy, PartialOrd, Eq, Ord, Debug, Hash)]
#[rustc_diagnostic_item = "Option"]
#[cfg_attr(not(bootstrap), lang = "Option")]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Option<T> {
    /// No value.
    #[lang = "None"]
    #[stable(feature = "rust1", since = "1.0.0")]
    None,
    /// Some value of type `T`.
    #[lang = "Some"]
    #[stable(feature = "rust1", since = "1.0.0")]
    Some(#[stable(feature = "rust1", since = "1.0.0")] T),
}

It seems like Option<T> derived Copy trait, so the first example should be fine.

Did I miss anything from the module-level documentation?


Solution

  • Using #[derive(Copy)] includes a T: Copy constraint. Meaning that Option<T> only implements Copy if T implements Copy.