Skip to content

Commit 2be3069

Browse files
committed
Improve mutability error suggestions.
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`.
1 parent 43b5d72 commit 2be3069

File tree

4 files changed

+67
-19
lines changed

4 files changed

+67
-19
lines changed

src/librustc_mir/borrow_check/mutability_errors.rs

+35
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc::mir::TerminatorKind;
1616
use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt};
1717
use rustc_data_structures::indexed_vec::Idx;
1818
use syntax_pos::Span;
19+
use syntax_pos::symbol::keywords;
1920

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

219220
match the_place_err {
221+
// Suggest removing a `&mut` from the use of a mutable reference.
222+
Place::Local(local)
223+
if {
224+
self.mir.local_decls.get(*local).map(|local_decl| {
225+
if let ClearCrossCrate::Set(
226+
mir::BindingForm::ImplicitSelf(kind)
227+
) = local_decl.is_user_variable.as_ref().unwrap() {
228+
// Check if the user variable is a `&mut self` and we can therefore
229+
// suggest removing the `&mut`.
230+
//
231+
// Deliberately fall into this case for all implicit self types,
232+
// so that we don't fall in to the next case with them.
233+
*kind == mir::ImplicitSelfKind::MutRef
234+
} else if Some(keywords::SelfValue.name()) == local_decl.name {
235+
// Otherwise, check if the name is the self kewyord - in which case
236+
// we have an explicit self. Do the same thing in this case and check
237+
// for a `self: &mut Self` to suggest removing the `&mut`.
238+
if let ty::TyKind::Ref(
239+
_, _, hir::Mutability::MutMutable
240+
) = local_decl.ty.sty {
241+
true
242+
} else {
243+
false
244+
}
245+
} else {
246+
false
247+
}
248+
}).unwrap_or(false)
249+
} =>
250+
{
251+
err.span_label(span, format!("cannot {ACT}", ACT = act));
252+
err.span_label(span, "try removing `&mut` here");
253+
},
254+
220255
// We want to suggest users use `let mut` for local (user
221256
// variable) mutations...
222257
Place::Local(local) if self.mir.local_decls[*local].can_be_made_mutable() => {

src/test/ui/did_you_mean/issue-31424.nll.stderr

+8-4
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,19 @@ error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
22
--> $DIR/issue-31424.rs:17:9
33
|
44
LL | (&mut self).bar(); //~ ERROR cannot borrow
5-
| ^^^^^^^^^^^ cannot borrow as mutable
5+
| ^^^^^^^^^^^
6+
| |
7+
| cannot borrow as mutable
8+
| try removing `&mut` here
69

710
error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
811
--> $DIR/issue-31424.rs:23:9
912
|
10-
LL | fn bar(self: &mut Self) {
11-
| ---- help: consider changing this to be mutable: `mut self`
1213
LL | (&mut self).bar(); //~ ERROR cannot borrow
13-
| ^^^^^^^^^^^ cannot borrow as mutable
14+
| ^^^^^^^^^^^
15+
| |
16+
| cannot borrow as mutable
17+
| try removing `&mut` here
1418

1519
error: aborting due to 2 previous errors
1620

src/test/ui/nll/issue-51191.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,28 @@ struct Struct;
1414

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

2021
fn imm(self) {
21-
(&mut self).bar(); //~ ERROR cannot borrow
22+
(&mut self).bar();
23+
//~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596]
2224
}
2325

2426
fn mtbl(mut self) {
2527
(&mut self).bar();
2628
}
2729

2830
fn immref(&self) {
29-
(&mut self).bar(); //~ ERROR cannot borrow
31+
(&mut self).bar();
32+
//~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596]
33+
//~^^ ERROR cannot borrow data in a `&` reference as mutable [E0596]
3034
}
3135

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

src/test/ui/nll/issue-51191.stderr

+16-12
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,40 @@
11
error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
22
--> $DIR/issue-51191.rs:17:9
33
|
4-
LL | fn bar(self: &mut Self) {
5-
| ---- help: consider changing this to be mutable: `mut self`
6-
LL | (&mut self).bar(); //~ ERROR cannot borrow
7-
| ^^^^^^^^^^^ cannot borrow as mutable
4+
LL | (&mut self).bar();
5+
| ^^^^^^^^^^^
6+
| |
7+
| cannot borrow as mutable
8+
| try removing `&mut` here
89

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

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

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

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

3539
error: aborting due to 5 previous errors
3640

0 commit comments

Comments
 (0)