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

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

Closed
oberien opened this issue May 29, 2018 · 3 comments
Closed
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@oberien
Copy link
Contributor

oberien commented May 29, 2018

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
@abonander
Copy link
Contributor

abonander commented Aug 30, 2018

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

@arielb1
Copy link
Contributor

arielb1 commented Sep 1, 2018

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.

@XAMPPRocky XAMPPRocky added C-enhancement Category: An issue proposing an enhancement or a PR with one. 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 Oct 2, 2018
@estebank
Copy link
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
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. 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

5 participants