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

Poor error message when the LHS of an assignment must be dereferenced #46276

Open
stjepang opened this issue Nov 26, 2017 · 2 comments
Open

Poor error message when the LHS of an assignment must be dereferenced #46276

stjepang opened this issue Nov 26, 2017 · 2 comments

Comments

@stjepang
Copy link
Contributor

@stjepang stjepang commented Nov 26, 2017

Code (also available on playground):

use std::sync::Mutex;

fn main() {
    let a = Mutex::new(7);
    let mut a = a.lock().unwrap();
    a += 1;
}

Error:

error[E0368]: binary assignment operation `+=` cannot be applied to type `std::sync::MutexGuard<'_, {integer}>`
 --> src/main.rs:6:5
  |
6 |     a += 1;
  |     -^^^^^
  |     |
  |     cannot use `+=` on type `std::sync::MutexGuard<'_, {integer}>`

Okay, but why cannot += be applied to Mutexuard<'_, {integer}>? And what can we do about it? :)

I'd prefer if the error message included something like:

help: consider dereferencing the left-hand side: `*a += 1`

Such a help message could be printed whenever the LHS of an assignment must be dereferenced. The same applies to situations in which we must dereference more than once, e.g **a.

@jimbo1qaz

This comment has been minimized.

Copy link

@jimbo1qaz jimbo1qaz commented Oct 24, 2019

I encountered a similar issue with terrible error messages. While my case (&mut) was resolved in Rust 1.37.0, OP's test code (MutexGuard) is not resolved.

When I first started learning Rust, I had written code similar to this:

fn f(items: &mut [i16]) {
    for item in items.iter_mut() {
        item = 1;
    }
}

For my original code, the error is now much better (testing in the Rust Playground). The error was apparently fixed in 1e3302d#diff-f6d957f8a5563c729f40e971cc767981 (1.37.0)? Now the error I get is:

error[E0308]: mismatched types
 --> src/lib.rs:3:16
  |
3 |         item = 1;
  |                ^ expected &mut i16, found integer
  |
  = note: expected type `&mut i16`
             found type `{integer}`
help: consider dereferencing here to assign to the mutable borrowed piece of memory
  |
3 |         *item = 1;
  |         ^^^^^

If I switch it to +=, I get:

error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut i16`
 --> src/lib.rs:3:9
  |
3 |         item += 1;
  |         ----^^^^^
  |         |
  |         cannot use `+=` on type `&mut i16`
help: `+=` can be used on 'i16', you can dereference `item`
  |
3 |         *item += 1;
  |         ^^^^^

This message is actually different from the = case. The test case for this message has existed since 2018 or before.


However, OP's case does not work.

error[E0368]: binary assignment operation `+=` cannot be applied to type `std::sync::MutexGuard<'_, {integer}>`
 --> src/main.rs:6:5
  |
6 |     a += 1;
  |     -^^^^^
  |     |
  |     cannot use `+=` on type `std::sync::MutexGuard<'_, {integer}>`
  |
  = note: an implementation of `std::ops::AddAssign` might be missing for `std::sync::MutexGuard<'_, {integer}>`

If I replace += with =, the error is still not meaningful:

error[E0308]: mismatched types
 --> src/main.rs:6:9
  |
6 |     a = 1;
  |         ^ expected struct `std::sync::MutexGuard`, found integer
  |
  = note: expected type `std::sync::MutexGuard<'_, {integer}>`
             found type `{integer}`

If I replace 7 with 7i32, the error is still bad:

error[E0308]: mismatched types
 --> src/main.rs:6:9
  |
6 |     a = 1;
  |         ^ expected struct `std::sync::MutexGuard`, found integer
  |
  = note: expected type `std::sync::MutexGuard<'_, i32>`
             found type `{integer}`

Apparently this bug is not solved for DerefMut types, producing bad errors on both = and +=. I implemented one such type in the playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d6ade7f9654c41dd867ff72df8519519

@nkaretnikov

This comment has been minimized.

Copy link

@nkaretnikov nkaretnikov commented Jan 3, 2020

Similar issue:

use std::sync::Mutex;

fn main() {
    let m = Mutex::new(42);
    
    let x = m.lock().unwrap();

    // println!("{}", *x - 1);
    println!("{}", x - 1);
    
    /*
    error[E0369]: cannot substract `{integer}` from `std::sync::MutexGuard<'_, {integer}>`
 --> src/main.rs:9:22
  |
9 |     println!("{}", x - 1);
  |                    - ^ - {integer}
  |                    |
  |                    std::sync::MutexGuard<'_, {integer}>
  |
  = note: an implementation of `std::ops::Sub` might be missing for `std::sync::MutexGuard<'_, {integer}>`
    */
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants
You can’t perform that action at this time.