Closed
Description
In #109429, a snippet of code involves cloning references outputted a confusing compiler error:
use std::collections::hash_map::DefaultHasher;
use std::collections::HashMap;
use std::hash::BuildHasher;
use std::hash::Hash;
pub struct Hash128_1;
impl BuildHasher for Hash128_1 {
type Hasher = DefaultHasher;
fn build_hasher(&self) -> DefaultHasher { DefaultHasher::default() }
}
#[allow(unused)]
pub fn hashmap_copy<T, U>(
map: &HashMap<T, U, Hash128_1>,
) where T: Hash + Clone, U: Clone
{
let mut copy: Vec<U> = map.clone().into_values().collect();
}
pub fn make_map() -> HashMap<String, i64, Hash128_1>
{
HashMap::with_hasher(Hash128_1)
}
error[E0507]: cannot move out of a shared reference
--> src/lib.rs:19:28
|
19 | let mut copy: Vec<U> = map.clone().into_values().collect();
| ^^^^^^^^^^^^-------------
| | |
| | value moved due to this method call
| move occurs because value has type `HashMap<T, U, Hash128_1>`, which does not implement the `Copy` trait
|
note: `HashMap::<K, V, S>::into_values` takes ownership of the receiver `self`, which moves value
Changing the diagnostic to provide help when we are trying to use a function that takes self
after a .clone()
call is nontrivial, since this is MIR borrowck and to my knowledge it is hard to know if it comes from the return value of a .clone()
call.
Ideally we should have an error/warning like the one from clippy:
error: using `clone` on a double-reference; this will copy the reference of type `&HashMap<T, U, Hash128_1>` instead of cloning the inner type
--> src/lib.rs:19:28
|
19 | let mut copy: Vec<U> = map.clone().into_values().collect();
| ^^^^^^^^^^^
I think there are other ways this can be confusing, so uplifting can help with many issues related to this and not just the example I linked.
cc @rust-lang/lang: would uplifting be a good idea? I'd be willing to work on this if this gets approval.
@rustbot label +A-lint +T-compiler +T-lang +D-newcomer-roadblock