Skip to content
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

"use of moved value" diagnostic could suggest reborrow when passing &mut to &mut #62112

Closed
pnkfelix opened this issue Jun 25, 2019 · 0 comments · Fixed by #73534
Closed

"use of moved value" diagnostic could suggest reborrow when passing &mut to &mut #62112

pnkfelix opened this issue Jun 25, 2019 · 0 comments · Fixed by #73534
Labels
A-borrow-checker Area: The borrow checker 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. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@pnkfelix
Copy link
Member

Spawned off of #45142

Consider the following code (play):

struct Events<R>(R);

struct Other;

pub trait Trait<T> { 
    fn handle(value: T) -> Self;
}

// Blanket impl. (If you comment this out, compiler figures out that it
// is passing an `&mut` to a method that must be expecting an `&mut`,
// and injects an auto-reborrow.)
impl<T, U> Trait<U> for T where T: From<U> {
    fn handle(_: U) -> Self { unimplemented!() }
}

impl<'a, R> Trait<&'a mut Events<R>> for Other {
    fn handle(_: &'a mut Events<R>) -> Self { unimplemented!() }
}

fn this_compiles<'a, R>(value: &'a mut Events<R>) {
    for _ in 0..3 {
        Other::handle(&mut *value);
    }
}

fn this_does_not<'a, R>(value: &'a mut Events<R>) {
    for _ in 0..3 {
        Other::handle(      value);
    }
}

fn main() {}

Today, this yields the diagnostic:

error[E0382]: use of moved value: `value`
  --> src/main.rs:30:29
   |
28 | fn this_does_not<'a, R>(value: &'a mut Events<R>) {
   |                         ----- move occurs because `value` has type `&mut Events<R>`, which does not implement the `Copy` trait
29 |     for _ in 0..3 {
30 |         Other::handle(      value);
   |                             ^^^^^ value moved here, in previous iteration of loop

We could do better. For example, the diagnostic could additionally say:

consider writing `Other::handle(&mut *value)` to create a fresh reborrow of `value`.

Background:

The compiler tries hard to auto-inject &mut-reborrows when it makes sense; as a way to create a fresh &mut reference to pass into the method invocation, and avoid moving the pre-existing &mut reference.

But there are times, often involving generic code, when it cannot automatically inject a reborrow. (After all, there are cases where the intent is to move the borrow into some place whose dynamic extent outlives that of the method invocation itself; and the static analysis cannot tell if this was the case at the point where it is deciding whether to insert an &mut-reborrow or not.)

This can lead to a diagnostic for the user telling them that they have a used of a moved value.

But new-comers to Rust do not always know about the option of putting in a &mut-reborrow themselves.

Our diagnostics could help them here. Even though we choose to not attempt to auto-inject the auto-reborrow in the compiler itself, our diagnostics have enough information about the method signature and the invocation to suggest to the user that they write out the &mut *value themselves.

@pnkfelix pnkfelix added A-diagnostics Area: Messages for errors, warnings, and lints A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix`. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-borrow-checker Area: The borrow checker and removed A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix`. labels Jun 25, 2019
@estebank estebank added the A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix`. label Jul 14, 2019
@estebank estebank added the D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. label Oct 5, 2019
@crlf0710 crlf0710 added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jun 11, 2020
estebank added a commit to estebank/rust that referenced this issue Jun 20, 2020
When encountering an used moved value where the previous move happened
in a `match` or `if let` pattern, suggest using `ref`. Fix rust-lang#63988.

When encountering a `&mut` value that is used in multiple iterations of
a loop, suggest reborrowing it with `&mut *`. Fix rust-lang#62112.
Manishearth added a commit to Manishearth/rust that referenced this issue Jun 21, 2020
…tthewjasper

Provide suggestions for some moved value errors

When encountering an used moved value where the previous move happened
in a `match` or `if let` pattern, suggest using `ref`. Fix rust-lang#63988.

When encountering a `&mut` value that is used in multiple iterations of
a loop, suggest reborrowing it with `&mut *`. Fix rust-lang#62112.
Manishearth added a commit to Manishearth/rust that referenced this issue Jun 22, 2020
…tthewjasper

Provide suggestions for some moved value errors

When encountering an used moved value where the previous move happened
in a `match` or `if let` pattern, suggest using `ref`. Fix rust-lang#63988.

When encountering a `&mut` value that is used in multiple iterations of
a loop, suggest reborrowing it with `&mut *`. Fix rust-lang#62112.
Manishearth added a commit to Manishearth/rust that referenced this issue Jun 26, 2020
…tthewjasper

Provide suggestions for some moved value errors

When encountering an used moved value where the previous move happened
in a `match` or `if let` pattern, suggest using `ref`. Fix rust-lang#63988.

When encountering a `&mut` value that is used in multiple iterations of
a loop, suggest reborrowing it with `&mut *`. Fix rust-lang#62112.
Manishearth added a commit to Manishearth/rust that referenced this issue Jun 26, 2020
…tthewjasper

Provide suggestions for some moved value errors

When encountering an used moved value where the previous move happened
in a `match` or `if let` pattern, suggest using `ref`. Fix rust-lang#63988.

When encountering a `&mut` value that is used in multiple iterations of
a loop, suggest reborrowing it with `&mut *`. Fix rust-lang#62112.
Manishearth added a commit to Manishearth/rust that referenced this issue Jun 26, 2020
…tthewjasper

Provide suggestions for some moved value errors

When encountering an used moved value where the previous move happened
in a `match` or `if let` pattern, suggest using `ref`. Fix rust-lang#63988.

When encountering a `&mut` value that is used in multiple iterations of
a loop, suggest reborrowing it with `&mut *`. Fix rust-lang#62112.
@bors bors closed this as completed in 520461f Jun 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-borrow-checker Area: The borrow checker 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. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants