Skip to content

Add suggestion/explanation to error on trying to mutably borrow immutable reference #45405

Open
@oli-obk

Description

@oli-obk
Contributor
    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:

  1. The easy way this error message can be improved is to mention that the type is &T, but should be &mut T.
  2. If there are explicit type annotations on the variable, a note should point to it
  3. 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.

Activity

added
C-enhancementCategory: An issue proposing an enhancement or a PR with one.
on Oct 22, 2017
estebank

estebank commented on Dec 13, 2018

@estebank
Contributor

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 mutable

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

added
D-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.
D-papercutDiagnostics: An error or lint that needs small tweaks.
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Feb 14, 2020
estebank

estebank commented on Feb 3, 2023

@estebank
Contributor

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 mutable
added a commit that references this issue on Feb 4, 2023

Rollup merge of rust-lang#107646 - estebank:specific-span, r=compiler…

d381eca
estebank

estebank commented on May 2, 2024

@estebank
Contributor

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 as casting 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.

added
P-lowLow priority
and removed
D-papercutDiagnostics: An error or lint that needs small tweaks.
D-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.
on May 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsC-enhancementCategory: An issue proposing an enhancement or a PR with one.P-lowLow priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.WG-diagnosticsWorking group: Diagnostics

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @kennytm@oli-obk@TimNN@estebank

        Issue actions

          Add suggestion/explanation to error on trying to mutably borrow immutable reference · Issue #45405 · rust-lang/rust