Skip to content

Commit

Permalink
Improve mutability error suggestions.
Browse files Browse the repository at this point in the history
This commit improves mutability error suggestions by suggesting the
removal of `&mut` where a mutable borrow is being taken of a `&mut self`
or a `self: &mut Self`.
  • Loading branch information
davidtwco committed Oct 1, 2018
1 parent 43b5d72 commit 2be3069
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 19 deletions.
35 changes: 35 additions & 0 deletions src/librustc_mir/borrow_check/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use rustc::mir::TerminatorKind;
use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt};
use rustc_data_structures::indexed_vec::Idx;
use syntax_pos::Span;
use syntax_pos::symbol::keywords;

use dataflow::move_paths::InitLocation;
use borrow_check::MirBorrowckCtxt;
Expand Down Expand Up @@ -217,6 +218,40 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
debug!("report_mutability_error: act={:?}, acted_on={:?}", act, acted_on);

match the_place_err {
// Suggest removing a `&mut` from the use of a mutable reference.
Place::Local(local)
if {
self.mir.local_decls.get(*local).map(|local_decl| {
if let ClearCrossCrate::Set(
mir::BindingForm::ImplicitSelf(kind)
) = local_decl.is_user_variable.as_ref().unwrap() {
// Check if the user variable is a `&mut self` and we can therefore
// suggest removing the `&mut`.
//
// Deliberately fall into this case for all implicit self types,
// so that we don't fall in to the next case with them.
*kind == mir::ImplicitSelfKind::MutRef
} else if Some(keywords::SelfValue.name()) == local_decl.name {
// Otherwise, check if the name is the self kewyord - in which case
// we have an explicit self. Do the same thing in this case and check
// for a `self: &mut Self` to suggest removing the `&mut`.
if let ty::TyKind::Ref(
_, _, hir::Mutability::MutMutable
) = local_decl.ty.sty {
true
} else {
false
}
} else {
false
}
}).unwrap_or(false)
} =>
{
err.span_label(span, format!("cannot {ACT}", ACT = act));
err.span_label(span, "try removing `&mut` here");
},

// We want to suggest users use `let mut` for local (user
// variable) mutations...
Place::Local(local) if self.mir.local_decls[*local].can_be_made_mutable() => {
Expand Down
12 changes: 8 additions & 4 deletions src/test/ui/did_you_mean/issue-31424.nll.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@ error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
--> $DIR/issue-31424.rs:17:9
|
LL | (&mut self).bar(); //~ ERROR cannot borrow
| ^^^^^^^^^^^ cannot borrow as mutable
| ^^^^^^^^^^^
| |
| cannot borrow as mutable
| try removing `&mut` here

error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
--> $DIR/issue-31424.rs:23:9
|
LL | fn bar(self: &mut Self) {
| ---- help: consider changing this to be mutable: `mut self`
LL | (&mut self).bar(); //~ ERROR cannot borrow
| ^^^^^^^^^^^ cannot borrow as mutable
| ^^^^^^^^^^^
| |
| cannot borrow as mutable
| try removing `&mut` here

error: aborting due to 2 previous errors

Expand Down
11 changes: 8 additions & 3 deletions src/test/ui/nll/issue-51191.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,28 @@ struct Struct;

impl Struct {
fn bar(self: &mut Self) {
(&mut self).bar(); //~ ERROR cannot borrow
(&mut self).bar();
//~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596]
}

fn imm(self) {
(&mut self).bar(); //~ ERROR cannot borrow
(&mut self).bar();
//~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596]
}

fn mtbl(mut self) {
(&mut self).bar();
}

fn immref(&self) {
(&mut self).bar(); //~ ERROR cannot borrow
(&mut self).bar();
//~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596]
//~^^ ERROR cannot borrow data in a `&` reference as mutable [E0596]
}

fn mtblref(&mut self) {
(&mut self).bar();
//~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596]
}
}

Expand Down
28 changes: 16 additions & 12 deletions src/test/ui/nll/issue-51191.stderr
Original file line number Diff line number Diff line change
@@ -1,36 +1,40 @@
error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
--> $DIR/issue-51191.rs:17:9
|
LL | fn bar(self: &mut Self) {
| ---- help: consider changing this to be mutable: `mut self`
LL | (&mut self).bar(); //~ ERROR cannot borrow
| ^^^^^^^^^^^ cannot borrow as mutable
LL | (&mut self).bar();
| ^^^^^^^^^^^
| |
| cannot borrow as mutable
| try removing `&mut` here

error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
--> $DIR/issue-51191.rs:21:9
--> $DIR/issue-51191.rs:22:9
|
LL | fn imm(self) {
| ---- help: consider changing this to be mutable: `mut self`
LL | (&mut self).bar(); //~ ERROR cannot borrow
LL | (&mut self).bar();
| ^^^^^^^^^^^ cannot borrow as mutable

error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
--> $DIR/issue-51191.rs:29:9
--> $DIR/issue-51191.rs:31:9
|
LL | (&mut self).bar(); //~ ERROR cannot borrow
LL | (&mut self).bar();
| ^^^^^^^^^^^ cannot borrow as mutable

error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/issue-51191.rs:29:9
--> $DIR/issue-51191.rs:31:9
|
LL | (&mut self).bar(); //~ ERROR cannot borrow
LL | (&mut self).bar();
| ^^^^^^^^^^^ cannot borrow as mutable

error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
--> $DIR/issue-51191.rs:33:9
--> $DIR/issue-51191.rs:37:9
|
LL | (&mut self).bar();
| ^^^^^^^^^^^ cannot borrow as mutable
| ^^^^^^^^^^^
| |
| cannot borrow as mutable
| try removing `&mut` here

error: aborting due to 5 previous errors

Expand Down

0 comments on commit 2be3069

Please sign in to comment.