Skip to content

Improve error message "cannot borrow immutable Box content **f as mutable" #51157

Description

@oberien
fn test(f: Box<FnMut()>) {
    let _f = move || {
        f()
    };
}

error[E0596]: cannot borrow immutable `Box` content `**f` as mutable
 --> src/main.rs:3:9
  |
3 |         f()
  |         ^ cannot borrow as mutable

This error message seems a bit weird, because the problem isn't that box content isn't mutable, but the box itself is immutable. Changing the line 2 to let mut f: … fixes the issue. Notice that the same error message is shown if we construct f within the function.

I think the error message should be improved to look similar to the following (not sure on the phrasing of the error itself):

error[E0596]: cannot borrow immutable argument `Box` as mutable
 --> src/main.rs:2:5
  |
1 | fn test(f: Box<FnMut()>) {
  |         - consider changing this to `mut f`
2 |     let _f = move || {
3 |         f()
  |         ^ cannot borrow mutably

Activity

  1. abonander commented on Aug 30, 2018

    @abonander
    Contributor

    A user on Reddit ran into a similar case but the appropriate binding is marked mut: https://old.reddit.com/r/rust/comments/9amj6w/hey_rustaceans_got_an_easy_question_ask_here/e50wrlv/

    I put box in a cell:

    let notify: RefCell<Box<dyn FnMut()>> = RefCell::new(Box::new(|| {}));
    

    next I borrowed it:

    let mut ref_mut = notify.borrow_mut();
    

    now for some reason I cannot call it, ref_mut() gives an error:

    error[E0596]: cannot borrow immutable `Box` content as mutable
     --> src/main.rs:6:5
      |
    6 |     ref_mut();
      |     ^^^^^^^ cannot borrow as mutable
    

    As a workaround I can call it as (&mut *ref_mut)() but why is this &mut * required?

    My hypothesis is that the call operator is only attempting immutable deref coercion and requires the deref-reref as a hint to attempt mutable deref coercion instead, but that's a mostly uneducated guess. This seems to be supported by the additional unused_mut warning emitted afterwards concerning ref_mut:

    warning: variable does not need to be mutable
     --> src/main.rs:5:9
      |
    5 |     let mut ref_mut = refcell.borrow_mut();
      |         ----^^^^^^^
      |         |
      |         help: remove this `mut`
      |
      = note: #[warn(unused_mut)] on by default
  2. arielb1 commented on Sep 1, 2018

    @arielb1
    Contributor

    The OP's issue is just a piece of bad error reporting in AST borrowck, NLL gives the correct diagnostic:

    error[E0596]: cannot borrow `*f` as mutable, as `f` is not declared as mutable
     --> src/main.rs:4:9
      |
    2 | fn test(f: Box<FnMut()>) {
      |         - help: consider changing this to be mutable: `mut f`
    3 |     let _f = move || {
    4 |         f()
      |         ^ cannot borrow as mutable

    The second issue is distinct, at it happens because overloaded call lookup uses an algorithm that is almost, but not quite, the same as method lookup. My proposal for rust-lang/rfcs#2147 would fix that.

  3. added
    C-enhancementCategory: An issue proposing an enhancement or a PR with one.
    A-diagnosticsArea: Messages for errors, warnings, and lints
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Oct 2, 2018
  4. estebank commented on Apr 14, 2019

    @estebank
    Contributor

    The first case is already fixed in stable when in 2018 mode and the one in the first message is cross posted in #28419.

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.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions