Skip to content

Misleading diagnostics when owning Option is used instead of an Option with a reference #43861

Closed
@kornelski

Description

@kornelski

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 type Foo
= 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-borrow-checkerArea: The borrow checkerA-diagnosticsArea: Messages for errors, warnings, and lintsC-enhancementCategory: An issue proposing an enhancement or a PR with one.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions