Compiler-Hint to assign to a mutably borrowed value

A beginner might try the following code:

fn main() {
    let mut some_val = 5;
    change_val(&mut some_val);
    println!("{}", some_val);

}

fn change_val(mut val: &mut i32) {
    val = &10;
}
error[E0308]: mismatched types
 --> src/main.rs:9:11
  |
9 |     val = &10;
  |           ^^^ types differ in mutability
  |
  = note: expected mutable reference `&mut _`
                     found reference `&_`

val needs to be a (mutable) reference, so the 10 is made a reference by using a &-Symbol in front of it. However this is not how you assign through a reference in this case but the compiler only suggest you to add a mut:

fn change_val(mut val: &mut i32) {
    val = &mut 10;
}
error[E0716]: temporary value dropped while borrowed
 --> src/main.rs:9:16
  |
8 | fn change_val(mut val: &mut i32) {
  |                        - let's call the lifetime of this reference `'1`
9 |     val = &mut 10;
  |     -----------^^- temporary value is freed at the end of this statement
  |     |          |
  |     |          creates a temporary value which is freed while still in use
  |     assignment requires that borrow lasts for `'1`

This creates another, not working, piece of code. Now val doesn't live long enough.

Parallel to the errors, the compiler should hint you to assign through the reference, like with this implementation:

fn main() {
    let mut some_val = 5;
    change_val(&mut some_val);
    println!("{}", some_val);

}

fn change_val(mut val: &mut i32) {
    val = 10;
}
error[E0308]: mismatched types
 --> src/main.rs:9:11
  |
8 | fn change_val(mut val: &mut i32) {
  |                        -------- expected due to this parameter type
9 |     val = 10;
  |           ^^ expected `&mut i32`, found integer
  |
help: consider dereferencing here to assign to the mutably borrowed value
  |
9 |     *val = 10;
  |     +

The current status can be confusing and frustrating for rust-beginners. Especially if they come from languages like Java. A hint like this could help beginners.

2 Likes

Note that after https://github.com/rust-lang/rust/pull/134977, if you match the mutability you get

warning: value assigned to `val` is never read
 --> src/main.rs:9:5
  |
9 |     val = &mut 10;
  |     ^^^
  |
  = note: `#[warn(unused_assignments)]` on by default
help: you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding
  |
8 ~ fn change_val(val: &mut mut i32) {
9 ~     *val = 10;
  |

warning: unused variable: `val`
 --> src/main.rs:8:19
  |
8 | fn change_val(mut val: &mut i32) {
  |                   ^^^ help: if this is intentional, prefix it with an underscore: `_val`
  |
  = note: `#[warn(unused_variables)]` on by default

error[E0716]: temporary value dropped while borrowed
 --> src/main.rs:9:16
  |
8 | fn change_val(mut val: &mut i32) {
  |                        - let's call the lifetime of this reference `'1`
9 |     val = &mut 10;
  |     -----------^^- temporary value is freed at the end of this statement
  |     |          |
  |     |          creates a temporary value which is freed while still in use
  |     assignment requires that borrow lasts for `'1`

Note the suggestion in the lint.


Regardless, I agree it'd be nice to detect the case you mentioned. Can you file a ticket with the same content as your thread comment?

Thanks for your Input.

How exactly do I file a Ticket? Im being lead back here when I try to create a feature request on the github-repo.

Do I just use the blank template?

"New Issue" then "Diagnostic Issue" will bring up this form