Add suggestion/explanation to error on trying to mutably borrow immutable reference
let mut mem_buffer : &[u8] = &b"foo"[..];
let mut reader = &mut mem_buffer as &std::io::Read;
let mut read_buffer = [0u8, 10];
reader.read(&mut read_buffer);
reports
error[E0596]: cannot borrow immutable borrowed content `*reader` as mutable
--> src/main.rs:5:5
|
5 | reader.read(&mut read_buffer);
| ^^^^^^ cannot borrow as mutable
Which is correct, but the fix is to modify the creation of the reader variable. While this case is easy, it's probably less so in the general case. Possible avenues of improvement:
- The easy way this error message can be improved is to mention that the type is
&T, but should be&mut T. - If there are explicit type annotations on the variable, a note should point to it
- If the variable's type is inferred, a note should point to its initializer and maybe even do some primitive checks that can lead the developer towards the solution.
Current output:
warning: variable does not need to be mutable --> src/main.rs:3:9 | 3 | let mut reader = &mut mem_buffer as &std::io::Read; | ----^^^^^^ | | | help: remove this `mut` | = note: #[warn(unused_mut)] on by default error[E0596]: cannot borrow `*reader` as mutable, as it is behind a `&` reference --> src/main.rs:5:5 | 3 | let mut reader = &mut mem_buffer as &std::io::Read; | --------------------------------- help: consider changing this to be a mutable reference: `&mut mut mem_buffer as &std::io::Read` 4 | let mut read_buffer = [0u8, 10]; 5 | reader.read(&mut read_buffer); | ^^^^^^ `reader` is a `&` reference, so the data it refers to cannot be borrowed as mutableApplying the suggestion is (correctly) a parse error. We need to change that suggestion to find the appropriate place for the
mut: it should be&mut mem_buffer as &mut std::io::Read.Esteban Kuber at 2018-12-13 01:16:59
Current output:
error[E0596]: cannot borrow `*reader` as mutable, as it is behind a `&` reference --> src/main.rs:5:5 | 3 | let mut reader = &mut mem_buffer as &dyn std::io::Read; | ---------- consider changing this binding's type to be: `&mut dyn std::io::Read` 4 | let mut read_buffer = [0u8, 10]; 5 | reader.read(&mut read_buffer); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `reader` is a `&` reference, so the data it refers to cannot be borrowed as mutableEsteban Kuber at 2023-02-03 15:57:57
Current output:
error[E0596]: cannot borrow `*reader` as mutable, as it is behind a `&` reference --> src/main.rs:5:5 | 5 | reader.read(&mut read_buffer); | ^^^^^^ `reader` is a `&` reference, so the data it refers to cannot be borrowed as mutable | help: consider specifying this binding's type | 3 | let mut reader: &mut dyn std::io::Read = &mut mem_buffer as &dyn std::io::Read; | ++++++++++++++++++++++++Applying the suggestion we get
error[E0308]: mismatched types --> src/main.rs:3:46 | 3 | let mut reader: &mut dyn std::io::Read = &mut mem_buffer as &dyn std::io::Read; | ---------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability | | | expected due to this | = note: expected mutable reference `&mut dyn std::io::Read` found reference `&dyn std::io::Read`Only thing left is to detect when an E0308 is pointing at an
ascasting expression and point only at the type part of it, and opportunistically suggest changing it to the right type. Having said that, I'm satisfied with the current output.Esteban Kuber at 2024-05-02 00:33:38