Skip to content

Unclear clear error message for borrowed contexts #25507

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
ghost opened this issue May 16, 2015 · 8 comments
Closed

Unclear clear error message for borrowed contexts #25507

ghost opened this issue May 16, 2015 · 8 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` 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.

Comments

@ghost
Copy link

ghost commented May 16, 2015

The error message for the following snippet could be improved, from IRC I was told to add .iter() onto line 7 (which worked). I believe a hint in the error message would be helpful.

struct MyStruct {
    member : Vec<u8>,
}

impl MyStruct {
    fn example (&self) {
        for foo in self.member { // line 7
            println!("{}", foo);
        }
    }
}

fn main() {
    let a = MyStruct { member : vec!(1, 2, 3) };
    a.example();
}

Error seen:

src/main.rs:7:20: 7:24 error: cannot move out of borrowed content
src/main.rs:7         for foo in self.member {
                                 ^~~~
note: in expansion of for loop expansion
src/main.rs:7:9: 9:10 note: expansion site
error: aborting due to previous error

rustc --version --verbose:

rustc 1.1.0-nightly (e5394240a 2015-05-14) (built 2015-05-13)
binary: rustc
commit-hash: e5394240a295650b567aa406b4a0e1e3a6749a5f
commit-date: 2015-05-14
build-date: 2015-05-13
host: x86_64-apple-darwin
release: 1.1.0-nightly
@Stebalien
Copy link
Contributor

This could definitely be improved. Just as an FYI, for loops take IntoIterators by-value so the following also works:

for foo in &self.member {
    // ...
}

This is because IntoIterator is implemented on both &Vec<T> (producing an iterator that yields references to the items) and Vec<T> (producing an iterator that yields the items by value and consumes the vector.

We should probably add a detailed error message for this case; you're not the first to be confused.

@steveklabnik steveklabnik added the A-diagnostics Area: Messages for errors, warnings, and lints label May 18, 2015
@luke-gru
Copy link

I just stumbled into this, +1 for more helpful error message

@Eoin-ONeill-Yokai
Copy link

I also stumbled upon this myself. Adding iter() also worked. +1 for better error message handling...

@jleedev
Copy link

jleedev commented Nov 23, 2016

I just ran into this. Here's a slightly different example:

#[derive(Debug)]
struct X;  // not Copy

struct Y{field: Option<X>}

fn main() {
    let v: Vec<Y> = Vec::new();
    for y in v.iter() {
        println!("{:?}", y.field.unwrap_or(X));
    }
}

Error:

rustc 1.13.0 (2c6933acc 2016-11-07)
error[E0507]: cannot move out of borrowed content
 --> <anon>:9:26
  |
9 |         println!("{:?}", y.field.unwrap_or(X));
  |                          ^ cannot move out of borrowed content

Ultimately, the diagnostic here should explain why something is being moved, and what was borrowed in the first place. Namely, it's because the call to unwrap_or takes self.

The lifecycle of my example is worth nothing as well: The loop originally iterated over just v, which implicitly calls into_iter(), but I manually inserted iter() to make enumerate() work. No clue if it's generally useful, but a hint "did you mean into_iter" would have helped me here.

@steveklabnik steveklabnik added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 9, 2017
@jleedev
Copy link

jleedev commented May 8, 2017

This particular error pops up on me occasionally, so I have some more insight/complaints about my example. Let it: &Option<X>:

These three all give "cannot move out of borrowed content":

it.unwrap();
*it;
Option::unwrap(*it);

But this gives "expected type std::option::Option<_>, found type &std::option::Option<X>", which I think is more in line with my intent.

Option::unwrap(it);

When I type it.unwrap(), I am told that my error is an attempt to dereference it. But I think my error is in calling a method that takes ownership of a value which I have only borrowed. The compiler is inserting an implicit dereference and then chastising me about it.

@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 22, 2017
@steveklabnik
Copy link
Member

Triage: no changes, I do see people complain about this diagnostic fairly regularly...

@estebank
Copy link
Contributor

estebank commented Oct 2, 2019

Current output:

error[E0507]: cannot move out of `self.member` which is behind a shared reference
 --> src/main.rs:7:20
  |
7 |         for foo in self.member { // line 7
  |                    ^^^^^^^^^^^ move occurs because `self.member` has type `std::vec::Vec<u8>`, which does not implement the `Copy` trait

@estebank estebank added the A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` label Oct 2, 2019
@estebank
Copy link
Contributor

Current output:

error[E0507]: cannot move out of `self.member` which is behind a shared reference
 --> src/main.rs:7:20
  |
7 |         for foo in self.member { // line 7
  |                    ^^^^^^^^^^^
  |                    |
  |                    move occurs because `self.member` has type `std::vec::Vec<u8>`, which does not implement the `Copy` trait
  |                    help: consider iterating over a slice of the `Vec<_>`'s content: `&self.member`
error[E0507]: cannot move out of `y.field` which is behind a shared reference
 --> src/main.rs:9:26
  |
9 |         println!("{:?}", y.field.unwrap_or(X));
  |                          ^^^^^^^
  |                          |
  |                          move occurs because `y.field` has type `std::option::Option<X>`, which does not implement the `Copy` trait
  |                          help: consider borrowing the `Option`'s content: `y.field.as_ref()`

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 A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` 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.
Projects
None yet
Development

No branches or pull requests

7 participants