Skip to content

Unhelpful .clone() suggestion when moving a mutable reference #127285

Closed
@cyrgani

Description

@cyrgani

Code

struct X(u32);

impl X {
    fn f(&mut self) {
        generic(self);
        self.0 += 1;
    }
}

fn generic<T>(_x: T) {}

Current output

error[E0382]: use of moved value: `self`
  --> src/lib.rs:6:9
   |
4  |     fn f(&mut self) {
   |          --------- move occurs because `self` has type `&mut X`, which does not implement the `Copy` trait
5  |         generic(self);
   |                 ---- value moved here
6  |         self.0 += 1;
   |         ^^^^^^^^^^^ value used here after move
   |
note: consider changing this parameter type in function `generic` to borrow instead if owning the value isn't necessary
  --> src/lib.rs:10:19
   |
10 | fn generic<T>(_x: T) {}
   |    -------        ^ this parameter takes ownership of the value
   |    |
   |    in this function
help: consider cloning the value if the performance cost is acceptable
   |
5  |         generic(self).clone();
   |                      ++++++++

For more information about this error, try `rustc --explain E0382`.

Desired output

error[E0382]: use of moved value: `self`
  --> src/lib.rs:6:9
   |
4  |     fn f(&mut self) {
   |          --------- move occurs because `self` has type `&mut X`, which does not implement the `Copy` trait
5  |         generic(self);
   |                 ---- value moved here
6  |         self.0 += 1;
   |         ^^^^^^^^^^^ value used here after move
   |
note: consider changing this parameter type in function `generic` to borrow instead if owning the value isn't necessary
  --> src/lib.rs:10:19
   |
10 | fn generic<T>(_x: T) {}
   |    -------        ^ this parameter takes ownership of the value
   |    |
   |    in this function
help: consider reborrowing `self` instead
   |
5  |         generic(&mut *self);
   |                 ++++++

For more information about this error, try `rustc --explain E0382`.

Rationale and extra context

Cloning the returned value (which is ()) obviously doesn't help. But &mut T does not implement Clone, so changing the suggestion to clone self wouldn't help either. In fact, adding .clone() as suggested right now will error and suggest next:

help: consider cloning the value if the performance cost is acceptable
   |
5  |         generic(self).clone().clone();
   |                      ++++++++

And so on.

Instead, reborrowing self with generic(&mut *self) makes the code compile and should be suggested.

Thanks to bruh791 on the rust community discord server for explaining the problem and solution to me.

Other cases

No response

Rust Version

rustc 1.79.0 (129f3b996 2024-06-10)
binary: rustc
commit-hash: 129f3b9964af4d4a709d1383930ade12dfe7c081
commit-date: 2024-06-10
host: x86_64-unknown-linux-gnu
release: 1.79.0
LLVM version: 18.1.7

Anything else?

Replacing the use of

fn generic<T>(_x: T) {}

with

fn direct(_x: &mut X) {}

compiles even without reborrowing.

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsT-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