Description
struct Foo;
fn main() {
let x = Some(Foo);
if let Some(ref y) = x {
foo(y.clone());
}
}
fn foo(x: Foo) {}
This gives the very unintuitive error:
error: mismatched types [--explain E0308]
--> <anon>:5:13
5 |> foo(y.clone());
|> ^^^^^^^^^ expected struct `Foo`, found &-ptr
note: expected type `Foo`
note: found type `&Foo`
You expect y.clone()
to return (*y).clone()
, i.e. a Foo
. It mysteriously returns an &Foo
instead.
Because &T
has a clone impl, it too, can be cloned (really, copied), returning a reference of the same lifetime. This is an operation you rarely want to do explicitly, except when dealing with generics.
This error can crop up when you've forgotten to implement Clone
on Foo
, and have a reference (which could have been silently inserted using ref
, as in the code above). However, it's not very obvious what's happening here. It can also crop up if you forget a T: Clone
bound
We should hint that Foo
itself isn't cloneable and thus we fell back to cloning &Foo
here.
This could be a lint on hitting the clone impl for references, but lints run too late.
I'm not sure how this can be implemented, since we need to see the source of a value and that's a bit tricky.