Description
There's an unfortunate effect of type-checking done before borrow checking, when the root of the type error is due to use of owned value instead of a reference.
Specifically, common uses of .map()
/.and_then()
/if let Some()
on &Option<T: !Copy>
are likely to fail with a misleading error.
When the inner value is used as if it was a reference it causes an error that is technically correct, but ultimately unhelpful and misleading:
= note: expected type
&Foo
found typeFoo
= help: try with&arg
This hint is wrong, because actually using &arg
gives the dreaded:
cannot move out of borrowed content
and this error doesn't have any suggestion how to proceed, so it's a scary dead-end for someone struggling with the borrow checker.
The correct solution is to suggest calling .as_ref()
on Option
. Here's an example:
struct Foo;
fn takes_ref(_: &Foo) {}
fn main() {
let ref opt = Some(Foo);
opt.map(|arg| takes_ref(arg));
// ^ suggests: opt.map(|arg| take_ref(&arg));
opt.as_ref().map(|arg| takes_ref(arg));
// ^ this should be done instead
}
I find it to be a big problem, because in Rust it's easy to end up with &Option<T>
. To a novice it's not obvious that it can be converted to Option<&T>
that works, and Rust doesn't suggest that solution.
Due to borrow checker depending on type-checking it's probably impossible to improve this diagnostic in general case, but I suggest at least special-casing it for Option
(suggesting .as_ref()
), since it's such a common pitfall.