about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorDavid Wood <david@davidtw.co>2018-10-01 19:20:57 +0200
committerDavid Wood <david@davidtw.co>2018-10-02 00:35:15 +0200
commit2be306939dae233ae641ebd692ef45840bb419cb (patch)
tree8c880476d12eaf47c4fd5ca31a9b242c95eef539 /src
parent43b5d725d0b458e317c52ef200d323998fa0c20f (diff)
downloadrust-2be306939dae233ae641ebd692ef45840bb419cb.tar.gz
rust-2be306939dae233ae641ebd692ef45840bb419cb.zip
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`.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/borrow_check/mutability_errors.rs35
-rw-r--r--src/test/ui/did_you_mean/issue-31424.nll.stderr12
-rw-r--r--src/test/ui/nll/issue-51191.rs11
-rw-r--r--src/test/ui/nll/issue-51191.stderr28
4 files changed, 67 insertions, 19 deletions
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index 1d33d9cc0c4..ba625fb08c8 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -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;
@@ -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() => {
diff --git a/src/test/ui/did_you_mean/issue-31424.nll.stderr b/src/test/ui/did_you_mean/issue-31424.nll.stderr
index eae834e2b1a..15139e4e8ae 100644
--- a/src/test/ui/did_you_mean/issue-31424.nll.stderr
+++ b/src/test/ui/did_you_mean/issue-31424.nll.stderr
@@ -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
 
diff --git a/src/test/ui/nll/issue-51191.rs b/src/test/ui/nll/issue-51191.rs
index 3dd6c629fc7..87ec3e5df0b 100644
--- a/src/test/ui/nll/issue-51191.rs
+++ b/src/test/ui/nll/issue-51191.rs
@@ -14,11 +14,13 @@ 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) {
@@ -26,11 +28,14 @@ impl Struct {
     }
 
     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]
     }
 }
 
diff --git a/src/test/ui/nll/issue-51191.stderr b/src/test/ui/nll/issue-51191.stderr
index e56ddb1ed53..c5b5218f173 100644
--- a/src/test/ui/nll/issue-51191.stderr
+++ b/src/test/ui/nll/issue-51191.stderr
@@ -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