Skip to content

Better suggested fix available for passing &mut (&mut val) #45392

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

Closed
FauxFaux opened this issue Oct 19, 2017 · 7 comments
Closed

Better suggested fix available for passing &mut (&mut val) #45392

FauxFaux opened this issue Oct 19, 2017 · 7 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics

Comments

@FauxFaux
Copy link

Given code like:

fn foo(a: &mut Bar) {}

fn baz(b: &mut Bar) {
    foo(&mut b)
}

rustc correctly points out that you "cannot borrow immutable argument b as mutable", and offers a fix of:

fn baz(b: &mut Bar) {
       - consider changing this to `mut b`

A better fix, in this case (and many others where I make this error), is to simply drop the &mut:

fn baz(b: &mut Bar) {
    foo(b)
}

I hit this error quite frequently, and remember finding the addition and removal of &mut until the compiler shut up about syntactic noise that I didn't care about (etc. etc.) pretty confusing; especially around Write.


Full code as a playground: https://play.rust-lang.org/?gist=9b69414d92287359bd6f1b91a53b254a&version=stable

If anyone can think of a better way to phrase the subject of this issue, please do change it.

@bluss bluss added A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. labels Oct 19, 2017
@Freyskeyd
Copy link
Contributor

I also found this disturbing.

I'm ok to work on a fix or an improvement of the suggestion.

If someone can mentor it... :)

@Mark-Simulacrum
Copy link
Member

cc @estebank @rust-lang/compiler - could someone provide mentoring instructions?

@kennytm kennytm added E-needs-mentor T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 20, 2017
@estebank
Copy link
Contributor

I believe that in the following code:

Some(ImmutabilityBlame::ImmLocal(node_id)) => {
let let_span = self.tcx.hir.span(node_id);
if let ty::BindByValue(..) = self.local_binding_mode(node_id) {
if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(let_span) {
let (_, is_implicit_self) = self.local_ty(node_id);
if is_implicit_self && snippet != "self" {
// avoid suggesting `mut &self`.
return
}
db.span_label(
let_span,
format!("consider changing this to `mut {}`", snippet)
);
}
}
}

we must verify that the mutability (the mut arg in ty::BindValue(mut), maybe) and check if the first field in the tuple returned local_ty is Some(ty.node == TyPtr(mut)) (definitely). If ty.node is a mutable reference, then the error span should receive a suggestion, instead of the current one. In order to do this, you have to change the signature for note_immutability_blame to also accept the error span.

@Freyskeyd apologies for not having seen this before. If you're still interested, feel free to reach out again here or in gitter! The amount of code shouldn't be too much, but there's a bunch of machinery you'd get familiar with (the DiagnosticBuilder and the node tree).

I believe the output should resemble the following (by using db.span_suggestion(sp, msg, snippet):


error[E0596]: cannot borrow immutable argument `b` as mutable
 --> src/main.rs:4:14
  |
4 |     foo(&mut b)
  |              ^ cannot borrow mutably
help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
4 |     foo(b)
  |         ^

@estebank estebank added WG-diagnostics Working group: Diagnostics E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. and removed E-needs-mentor labels Dec 13, 2017
@Freyskeyd
Copy link
Contributor

@estebank I'm interested, I will work on it next week.

@klnusbaum
Copy link
Contributor

@estebank This seemed kinda stale so I decided to try my hand at a fix. I opened a PR. I have a lot of questions, but I'll ask those in the PR.

@ytausky
Copy link
Contributor

ytausky commented May 24, 2018

Since @klnusbaum mentioned on #48708 that they're dropping this issue, I would like to do it.

bors added a commit that referenced this issue Jun 5, 2018
Suggest not mutably borrowing a mutable reference

This PR would (hopefully) solve #45392. I deviated a bit from @estebank's instructions since the error span only included the borrowed expression (e.g. the `b` in `&mut b`). I also didn't check the mutability of the local binding, since this whole case is concerned with an immutable local.

I can see two outstanding questions:
1. `note_immutability_blame` is called in two places, but I only have one test case. I think it covers the call in `report_bckerror`, but I'm not sure how to trigger the call from `report_aliasability_violation`.
2. There is one failing test, where the local binding is `self: &mut Self`. I'm not entirely sure what the correct output should be, but I think the new message should also apply. Unfortunately, since this parameter is parsed differently, its `let_span` covers both the pattern and the type, leading to a wrong suggestion text. I'm not sure how to correctly identify this case.
@ytausky
Copy link
Contributor

ytausky commented Jun 5, 2018

I think this issue can be closed now -- what's the process to do that?

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-bug Category: This is a bug. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics
Projects
None yet
Development

No branches or pull requests

8 participants