Skip to content

Improve error message when moving out of a &-reference #15457

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
nwin opened this issue Jul 5, 2014 · 7 comments
Closed

Improve error message when moving out of a &-reference #15457

nwin opened this issue Jul 5, 2014 · 7 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics

Comments

@nwin
Copy link
Contributor

nwin commented Jul 5, 2014

It would be nice if the following error message

test.rs:7:9: 7:13 error: cannot move out of dereference of `&`-pointer
test.rs:7         self.option.map(|x| x)
                  ^~~~
error: aborting due to previous error

would give a hint why exactly something was moved in the following code

struct Type {
    option: Option<Vec<u8>>
}

impl Type {
    fn method(&self) -> Option<Vec<u8>> {
        self.option.map(|x| x)
    }
}

fn main() {
    let _ = Type { option: None }.method();
}

Ideally "map takes option by value" or something like that.

@steveklabnik steveklabnik added the A-diagnostics Area: Messages for errors, warnings, and lints label Jan 23, 2015
@huonw huonw changed the title Improve error message when moving a &-reference Improve error message when moving out of a &-reference Jan 5, 2016
@steveklabnik steveklabnik added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 9, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 21, 2017
@estebank estebank added E-needs-mentor WG-diagnostics Working group: Diagnostics labels Dec 14, 2017
@estebank
Copy link
Contributor

Also reported in #25507 (comment)

@stokhos stokhos added the A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) label Feb 10, 2018
@estebank
Copy link
Contributor

estebank commented Feb 7, 2019

Possible final output:

error[E0507]: cannot move out of borrowed content
 --> src/main.rs:7:9
6 |    fn method(&self) -> Option<Vec<u8>> {
  |              ----- `self` is borrowed here
7 |        self.option.map(|x| x)
  |        ^^^^^^^^^^^ --- `map` consumes `self.option` here, moving it
  |        |
  |        cannot move out of borrowed content

@estebank estebank removed the A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) label Feb 7, 2019
@estebank
Copy link
Contributor

Output with #61147 applied:

error[E0507]: cannot move out of borrowed content
 --> file2.rs:7:9
  |
7 |         self.option.map(|x| x)
  |         ^^^^^^^^^^^
  |         |
  |         cannot move out of borrowed content
  |         help: consider borrowing the `Option`'s content: `self.option.as_ref()`

If applying the suggestion, we'll emit

error[E0308]: mismatched types
 --> file2.rs:7:9
  |
6 |     fn method(&self) -> Option<Vec<u8>> {
  |                         --------------- expected `std::option::Option<std::vec::Vec<u8>>` because of return type
7 |         self.option.as_ref().map(|x| x)
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found reference
  |
  = note: expected type `std::option::Option<std::vec::Vec<u8>>`
             found type `std::option::Option<&std::vec::Vec<u8>>`

bors added a commit that referenced this issue May 27, 2019
When encountering move error on an `Option`, suggest using `as_ref`

Fix #61109, cc #15457.
@estebank
Copy link
Contributor

estebank commented Oct 2, 2019

Current output:

error[E0507]: cannot move out of `self.option` which is behind a shared reference
 --> src/main.rs:7:9
  |
7 |         self.option.map(|x| x)
  |         ^^^^^^^^^^^
  |         |
  |         move occurs because `self.option` has type `std::option::Option<std::vec::Vec<u8>>`, which does not implement the `Copy` trait
  |         help: consider borrowing the `Option`'s content: `self.option.as_ref()`

@rylev
Copy link
Member

rylev commented Jul 5, 2021

Triage: no change (playground).

I believe the original suggestion of pointing to map as taking self and thus trying to move out of a &self is the right way to go to close this issue.

@TimJentzsch
Copy link

Current output with 1.65.0-nightly (2022-08-10 29e4a9ee0253cd39e552)

struct Type {
    option: Option<Vec<u8>>
}

impl Type {
    fn method(&self) -> Option<Vec<u8>> {
        self.option.as_ref().map(|x| x)
    }
}

fn main() {
    let _ = Type { option: None }.method();
}
error[[E0308]](https://doc.rust-lang.org/nightly/error-index.html#E0308): mismatched types
 --> src/main.rs:7:9
  |
6 |     fn method(&self) -> Option<Vec<u8>> {
  |                         --------------- expected `Option<Vec<u8>>` because of return type
7 |         self.option.as_ref().map(|x| x)
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Vec`, found `&Vec<u8>`
  |
  = note: expected enum `Option<Vec<u8>>`
             found enum `Option<&Vec<u8>>`

@estebank
Copy link
Contributor

estebank commented Jan 8, 2023

Current output

error[E0308]: mismatched types
 --> src/main.rs:7:9
  |
6 |     fn method(&self) -> Option<Vec<u8>> {
  |                         --------------- expected `Option<Vec<u8>>` because of return type
7 |         self.option.as_ref().map(|x| x)
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Vec`, found `&Vec<u8>`
  |
  = note: expected enum `Option<Vec<u8>>`
             found enum `Option<&Vec<u8>>`
help: use `Option::cloned` to clone the value inside the `Option`
  |
7 |         self.option.as_ref().map(|x| x).cloned()
  |                                        +++++++++
error[E0507]: cannot move out of `self.option` which is behind a shared reference
 --> src/main.rs:7:9
  |
7 |         self.option.map(|x| x)
  |         ^^^^^^^^^^^ ---------- `self.option` moved due to this method call
  |         |
  |         help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
  |         move occurs because `self.option` has type `Option<Vec<u8>>`, which does not implement the `Copy` trait
  |
note: `Option::<T>::map` takes ownership of the receiver `self`, which moves `self.option`
 --> /rustc/ee0412d1ef81efcfabe7f66cd21476ca85d618b1/library/core/src/option.rs:963:28
help: you can `clone` the value and consume it, but this might not be your desired behavior
  |
7 |         self.option.clone().map(|x| x)
  |                     ++++++++

@estebank estebank closed this as completed Jan 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics
Projects
None yet
Development

No branches or pull requests

7 participants