Skip to content

Compiler-Hint to assign to a mutably borrowed value #136026

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
ValonPrime opened this issue Jan 24, 2025 · 1 comment
Closed

Compiler-Hint to assign to a mutably borrowed value #136026

ValonPrime opened this issue Jan 24, 2025 · 1 comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@ValonPrime
Copy link

ValonPrime commented Jan 24, 2025

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;
}

Current output

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

Desired output

error[E0308]: mismatched types
 --> src/main.rs:9:11
  |
9 |     val = &10;
  |           ^^^ types differ in mutability
  |
  = note: expected mutable reference `&mut _`
                     found reference `&_`
help: consider dereferencing here to assign to the mutably borrowed value
  |
9 |     *val = 10;
  |     +

Rationale and extra context

A beginner might add a &-Symbol by themself, because val is a (mutable) reference. The output suggest adding a mut. However, assigning a mutably borrowed value might be desired in this case.

Internals: https://internals.rust-lang.org/t/compiler-hint-to-assign-to-a-mutably-borrowed-value/22209

Other cases

If you follow the current output and add the mut, one receives a Error about a too short lifetime.
I suggest the same hint in that case as well.

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`

and similar, when using a variable instead of a constant:

fn change_val(mut val: &mut i32) {
    let mut new_val = 10;
    val = &mut new_val;
}
error[E0597]: `new_val` does not live long enough
  --> src/main.rs:10:11
   |
8  | fn change_val(mut val: &mut i32) {
   |                        - let's call the lifetime of this reference `'1`
9  |     let mut new_val = 10;
   |         ----------- binding `new_val` declared here
10 |     val = &mut new_val;
   |     ------^^^^^^^^^^^^
   |     |     |
   |     |     borrowed value does not live long enough
   |     assignment requires that `new_val` is borrowed for `'1`
11 | }
   | - `new_val` dropped here while still borrowed

Rust Version

valon@valon:~/RustroverProjects/future_test$ rustc --version --verbose
rustc 1.84.0 (9fc6b4312 2025-01-07)
binary: rustc
commit-hash: 9fc6b43126469e3858e2fe86cafb4f0fd5068869
commit-date: 2025-01-07
host: x86_64-unknown-linux-gnu
release: 1.84.0
LLVM version: 19.1.5

Anything else?

No response

@ValonPrime ValonPrime added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 24, 2025
@cyrgani
Copy link
Contributor

cyrgani commented Jan 24, 2025

On nightly, a hint was already added (#134977):

fn change_val(mut val: &mut i32) {
    val = &mut 10;
}

produces

warning: value assigned to `val` is never read
 --> src/lib.rs:2:5
  |
2 |     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
  |
1 ~ fn change_val(val: &mut mut i32) {
2 ~     *val = 10;
  |

warning: unused variable: `val`
 --> src/lib.rs:1:19
  |
1 | 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/lib.rs:2:16
  |
1 | fn change_val(mut val: &mut i32) {
  |                        - let's call the lifetime of this reference `'1`
2 |     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`

The suggestion is actually invalid in this case, which is tracked by #136028, but it detects the case you describe.

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 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

2 participants