Skip to content

Moving out of field error should emit resolution suggestions #64167

Open

Description

@oli-cosmian

The current error doesn't help users resolve the problem. Even just including a message that one should try borrowing the field by prepending a & would be of help. I don't think it matters that this isn't possible for e.g. self.foo.consuming_method()

struct Foo {
    v: Vec<u32>,
}

impl Foo {
    fn bar(&self) {
        for _ in self.v {
            
        }
    }
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0507]: cannot move out of `self.v` which is behind a shared reference
 --> src/lib.rs:7:18
  |
7 |         for _ in self.v {
  |                  ^^^^^^ move occurs because `self.v` has type `std::vec::Vec<u32>`, which does not implement the `Copy` trait

error: aborting due to previous error

For more information about this error, try `rustc --explain E0507`.
error: Could not compile `playground`.

To learn more, run the command again with --verbose.

Activity

  1. added
    A-diagnosticsArea: Messages for errors, warnings, and lints
    A-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`
    C-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.
    on Sep 5, 2019
  2. estebank commented on Sep 5, 2019

    @estebank
    Contributor

    I could have sworn we had it already :-|

  3. added
    D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.
    on Oct 5, 2019
  4. added 2 commits that reference this issue on Jan 24, 2020
  5. cmpute commented on May 22, 2022

    @cmpute

    I have a case related to this issue:

    use std::ops::Neg;
    
    pub struct Foo<T>(pub T);
    
    impl<T: Neg<Output = T>> Neg for Foo<T> {
        type Output = Self;
        fn neg(self) -> Self {
            Foo(-self.0)
        }
    }
    
    impl<T: Neg<Output = T> + Clone> Neg for &Foo<T> {
        type Output = Foo<T>;
        fn neg(self) -> Self::Output {
            Foo(-self.0.clone())
        }
    }
    
    // pub fn test0<T: Neg>(f: Foo<T>) -> Foo<T>{
    //     f.neg()
    // }
    // pub fn test1<T: Neg>(f: Foo<T>) -> Foo<T>{
    //     -f
    // }
    pub fn test2<T: Neg<Output = T>>(f: Foo<T>) -> Foo<T>{
        -f
    }
    // pub fn test3<T: Neg<Output = T>>(f: &Foo<T>) -> Foo<T>{
    //     f.neg()
    // }
    pub fn test4<T: Neg<Output = T> + Clone>(f: &Foo<T>) -> Foo<T>{
        f.neg()
    }

    (Playground)

    In this case, test2 and test4 are correct implementation while the others are incorrect because they lack trait bounds. But the error messages on test1 and test3 are not very helpful.

    The error message for test0 is the most helpful one

    error[[E0599]](https://doc.rust-lang.org/nightly/error-index.html#E0599): the method `neg` exists for struct `Foo<T>`, but its trait bounds were not satisfied
      --> src/lib.rs:20:7
       |
    3  | pub struct Foo<T>(pub T);
       | -------------------------
       | |
       | method `neg` not found for this
       | doesn't satisfy `Foo<T>: Neg`
    ...
    20 |     f.neg()
       |       ^^^ method cannot be called on `Foo<T>` due to unsatisfied trait bounds
       |
    

    The error message for test1 is

    error[[E0600]](https://doc.rust-lang.org/nightly/error-index.html#E0600): cannot apply unary operator `-` to type `Foo<T>`
      --> src/lib.rs:20:5
       |
    20 |     -f
       |     ^^ cannot apply unary operator `-`
    
    For more information about this error, try `rustc --explain E0600`.
    

    The error message for test3 is

    error[[E0507]](https://doc.rust-lang.org/nightly/error-index.html#E0507): cannot move out of `*f` which is behind a shared reference
       --> src/lib.rs:20:5
        |
    20  |     f.neg()
        |     ^^-----
        |     | |
        |     | `*f` moved due to this method call
        |     move occurs because `*f` has type `Foo<T>`, which does not implement the `Copy` trait
        |
    note: this function takes ownership of the receiver `self`, which moves `*f`
    
    For more information about this error, try `rustc --explain E0507`.
    
  6. estebank commented on Nov 22, 2023

    @estebank
    Contributor

    Current output:

    error[E0507]: cannot move out of `self.v` which is behind a shared reference
       --> f75.rs:7:18
        |
    7   |         for _ in self.v {
        |                  ^^^^^^
        |                  |
        |                  `self.v` moved due to this implicit call to `.into_iter()`
        |                  move occurs because `self.v` has type `Vec<u32>`, which does not implement the `Copy` trait
        |
    note: `into_iter` takes ownership of the receiver `self`, which moves `self.v`
       --> /home/gh-estebank/rust/library/core/src/iter/traits/collect.rs:268:18
        |
    268 |     fn into_iter(self) -> Self::IntoIter;
        |                  ^^^^
    help: consider iterating over a slice of the `Vec<u32>`'s content to avoid moving into the `for` loop
        |
    7   |         for _ in &self.v {
        |                  +
    

    I believe that we are fully handling the original report. The report on the above comment is unchanged.

  7. removed
    C-enhancementCategory: An issue proposing an enhancement or a PR with one.
    A-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`
    D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.
    on Nov 22, 2023
  8. added a commit that references this issue on Apr 13, 2024
  9. estebank commented on Nov 3, 2025

    @estebank
    Contributor

    Current output:

    error[E0507]: cannot move out of `self.v` which is behind a shared reference
       --> src/lib.rs:7:18
        |
      7 |         for _ in self.v {
        |                  ^^^^^^
        |                  |
        |                  `self.v` moved due to this implicit call to `.into_iter()`
        |                  move occurs because `self.v` has type `Vec<u32>`, which does not implement the `Copy` trait
        |
    note: `into_iter` takes ownership of the receiver `self`, which moves `self.v`
       --> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/collect.rs:310:18
        |
    310 |     fn into_iter(self) -> Self::IntoIter;
        |                  ^^^^
    help: consider iterating over a slice of the `Vec<u32>`'s content to avoid moving into the `for` loop
        |
      7 |         for _ in &self.v {
        |                  +
    help: consider cloning the value if the performance cost is acceptable
        |
      7 |         for _ in self.v.clone() {
        |                        ++++++++
    
    error[E0599]: the method `neg` exists for struct `Foo<T>`, but its trait bounds were not satisfied
      --> src/lib.rs:20:7
       |
     3 | pub struct Foo<T>(pub T);
       | ----------------- method `neg` not found for this struct because it doesn't satisfy `Foo<T>: Neg`
    ...
    20 |     f.neg()
       |       ^^^ method cannot be called on `Foo<T>` due to unsatisfied trait bounds
       |
    note: trait bound `<T as Neg>::Output = T` was not satisfied
      --> src/lib.rs:5:13
       |
     5 | impl<T: Neg<Output = T>> Neg for Foo<T> {
       |             ^^^^^^^^^^   ---     ------
       |             |
       |             unsatisfied trait bound introduced here
    note: the following trait bounds were not satisfied:
          `<T as Neg>::Output = T`
          `T: Clone`
      --> src/lib.rs:12:13
       |
    12 | impl<T: Neg<Output = T> + Clone> Neg for &Foo<T> {
       |             ^^^^^^^^^^    ^^^^^  ---     -------
       |             |             |
       |             |             unsatisfied trait bound introduced here
       |             unsatisfied trait bound introduced here
    help: consider restricting the type parameter to satisfy the trait bound
       |
     3 | pub struct Foo<T>(pub T) where <T as Neg>::Output = T;
       |                          ++++++++++++++++++++++++++++
    help: consider restricting the type parameter to satisfy the trait bound
       |
    19 | pub fn test0<T: Neg>(f: Foo<T>) -> Foo<T> where T: Clone{
       |                                           ++++++++++++++
    
    error[E0600]: cannot apply unary operator `-` to type `Foo<T>`
      --> src/lib.rs:23:5
       |
    23 |     -f
       |     ^^ cannot apply unary operator `-`
    
    error[E0507]: cannot move out of `*f` which is behind a shared reference
       --> src/lib.rs:29:5
        |
     29 |     f.neg()
        |     ^ ----- `*f` moved due to this method call
        |     |
        |     move occurs because `*f` has type `Foo<T>`, which does not implement the `Copy` trait
        |
    note: `neg` takes ownership of the receiver `self`, which moves `*f`
       --> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/arith.rs:708:12
        |
    708 |     fn neg(self) -> Self::Output;
        |            ^^^^
    note: if `Foo<T>` implemented `Clone`, you could clone the value
       --> src/lib.rs:3:1
        |
      3 | pub struct Foo<T>(pub T);
        | ^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
    ...
     29 |     f.neg()
        |     - you could clone this value
    

    E0600 should reuse some of the context logic from E0599.

  10. added
    D-papercutDiagnostics: An error or lint that needs small tweaks.
    D-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.
    on Nov 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsD-papercutDiagnostics: An error or lint that needs small tweaks.D-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.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