about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2018-07-17 20:29:48 +0100
committerMatthew Jasper <mjjasper1@gmail.com>2018-07-20 20:01:15 +0100
commita06b2433fc2963dba4ef25deee6720c63ffcc03b (patch)
treec9136001bb8d382658622906043b0d18c6ec4f12
parent13b5f69848bf4ba9213fa60e7873f6ff51fc3afc (diff)
downloadrust-a06b2433fc2963dba4ef25deee6720c63ffcc03b.tar.gz
rust-a06b2433fc2963dba4ef25deee6720c63ffcc03b.zip
Update tests for new NLL mutability errors
-rw-r--r--src/test/compile-fail/E0594.rs2
-rw-r--r--src/test/compile-fail/borrowck/borrowck-assign-to-constants.rs2
-rw-r--r--src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs4
-rw-r--r--src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs2
-rw-r--r--src/test/ui/augmented-assignments.nll.stderr2
-rw-r--r--src/test/ui/borrowck/issue-45983.nll.stderr15
-rw-r--r--src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr2
-rw-r--r--src/test/ui/borrowck/mutability-errors.nll.stderr379
-rw-r--r--src/test/ui/borrowck/mutability-errors.rs92
-rw-r--r--src/test/ui/borrowck/mutability-errors.stderr308
-rw-r--r--src/test/ui/closure-immutable-outer-variable.nll.stderr4
-rw-r--r--src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-31424.nll.stderr4
-rw-r--r--src/test/ui/did_you_mean/issue-34126.nll.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-34337.nll.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-35937.nll.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-37139.nll.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-38147-1.nll.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-38147-2.nll.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-38147-3.nll.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-38147-4.nll.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-39544.nll.stderr22
-rw-r--r--src/test/ui/did_you_mean/issue-40823.nll.stderr2
-rw-r--r--src/test/ui/error-codes/E0017.nll.stderr2
-rw-r--r--src/test/ui/error-codes/E0388.nll.stderr2
-rw-r--r--src/test/ui/fn-closure-mutable-capture.nll.stderr8
-rw-r--r--src/test/ui/issue-21600.nll.stderr25
-rw-r--r--src/test/ui/issue-27282-reborrow-ref-mut-in-guard.rs2
-rw-r--r--src/test/ui/issue-27282-reborrow-ref-mut-in-guard.stderr10
-rw-r--r--src/test/ui/issue-33819.nll.stderr2
-rw-r--r--src/test/ui/issue-36400.nll.stderr2
-rw-r--r--src/test/ui/issue-41726.nll.stderr2
-rw-r--r--src/test/ui/issue-42344.nll.stderr2
-rw-r--r--src/test/ui/issue-46023.ast.nll.stderr5
-rw-r--r--src/test/ui/issue-46023.mir.stderr5
-rw-r--r--src/test/ui/issue-46023.rs2
-rw-r--r--src/test/ui/issue-46604.ast.nll.stderr2
-rw-r--r--src/test/ui/issue-46604.mir.stderr2
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr2
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr2
-rw-r--r--src/test/ui/macros/span-covering-argument-1.nll.stderr2
-rw-r--r--src/test/ui/nll/closure-captures.rs68
-rw-r--r--src/test/ui/nll/closure-captures.stderr160
-rw-r--r--src/test/ui/nll/generator-upvar-mutability.stderr5
-rw-r--r--src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr16
-rw-r--r--src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr8
-rw-r--r--src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr4
-rw-r--r--src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr2
-rw-r--r--src/test/ui/span/borrowck-fn-in-const-b.nll.stderr2
-rw-r--r--src/test/ui/span/borrowck-object-mutability.nll.stderr4
-rw-r--r--src/test/ui/span/mut-arg-hint.nll.stderr6
-rw-r--r--src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr4
52 files changed, 1128 insertions, 88 deletions
diff --git a/src/test/compile-fail/E0594.rs b/src/test/compile-fail/E0594.rs
index f3fbc3b8b54..e5e96451d13 100644
--- a/src/test/compile-fail/E0594.rs
+++ b/src/test/compile-fail/E0594.rs
@@ -15,5 +15,5 @@ static NUM: i32 = 18;
 
 fn main() {
     NUM = 20; //[ast]~ ERROR E0594
-              //[mir]~^ ERROR cannot assign to immutable item `NUM`
+              //[mir]~^ ERROR cannot assign to immutable static item `NUM`
 }
diff --git a/src/test/compile-fail/borrowck/borrowck-assign-to-constants.rs b/src/test/compile-fail/borrowck/borrowck-assign-to-constants.rs
index 76a670af353..57002dd40fc 100644
--- a/src/test/compile-fail/borrowck/borrowck-assign-to-constants.rs
+++ b/src/test/compile-fail/borrowck/borrowck-assign-to-constants.rs
@@ -16,5 +16,5 @@ static foo: isize = 5;
 fn main() {
     // assigning to various global constants
     foo = 6; //[ast]~ ERROR cannot assign to immutable static item
-             //[mir]~^ ERROR cannot assign to immutable item `foo`
+             //[mir]~^ ERROR cannot assign to immutable static item `foo`
 }
diff --git a/src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs b/src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs
index 8eed61ec8d5..6bd52f00788 100644
--- a/src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs
+++ b/src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs
@@ -22,10 +22,10 @@ fn main() {
     let x = 1;
     to_fn_once(move|| { x = 2; });
     //[ast]~^ ERROR: cannot assign to immutable captured outer variable
-    //[mir]~^^ ERROR: cannot assign to immutable item `x`
+    //[mir]~^^ ERROR: cannot assign to `x`, as it is not declared as mutable
 
     let s = std::io::stdin();
     to_fn_once(move|| { s.read_to_end(&mut Vec::new()); });
     //[ast]~^ ERROR: cannot borrow immutable captured outer variable
-    //[mir]~^^ ERROR: cannot borrow immutable item `s` as mutable
+    //[mir]~^^ ERROR: cannot borrow `s` as mutable, as it is not declared as mutable
 }
diff --git a/src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs b/src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs
index c7dc84c1a91..7b1dd9265af 100644
--- a/src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs
+++ b/src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs
@@ -17,5 +17,5 @@
 static FOO: isize = 5;
 
 fn main() {
-    FOO = 6; //~ ERROR cannot assign to immutable item `FOO` [E0594]
+    FOO = 6; //~ ERROR cannot assign to immutable static item `FOO` [E0594]
 }
diff --git a/src/test/ui/augmented-assignments.nll.stderr b/src/test/ui/augmented-assignments.nll.stderr
index 592f666eff8..57a86227f76 100644
--- a/src/test/ui/augmented-assignments.nll.stderr
+++ b/src/test/ui/augmented-assignments.nll.stderr
@@ -14,7 +14,7 @@ LL | |     x;  //~ value moved here
    | |_____move out of `x` occurs here
    |       borrow later used here
 
-error[E0596]: cannot borrow immutable item `y` as mutable
+error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
   --> $DIR/augmented-assignments.rs:30:5
    |
 LL |     let y = Int(2);
diff --git a/src/test/ui/borrowck/issue-45983.nll.stderr b/src/test/ui/borrowck/issue-45983.nll.stderr
index 68a039262c1..5a1f1986fcf 100644
--- a/src/test/ui/borrowck/issue-45983.nll.stderr
+++ b/src/test/ui/borrowck/issue-45983.nll.stderr
@@ -14,21 +14,14 @@ LL |     give_any(|y| x = Some(y));
    |               |
    |               lifetime `'1` appears in this argument
 
-error[E0594]: cannot assign to immutable item `x`
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
   --> $DIR/issue-45983.rs:17:18
    |
-LL |     give_any(|y| x = Some(y));
-   |                  ^^^^^^^^^^^ cannot assign
-
-error[E0596]: cannot borrow immutable item `x` as mutable
-  --> $DIR/issue-45983.rs:17:14
-   |
 LL |     let x = None;
    |         - help: consider changing this to be mutable: `mut x`
 LL |     give_any(|y| x = Some(y));
-   |              ^^^^^^^^^^^^^^^ cannot borrow as mutable
+   |                  ^^^^^^^^^^^ cannot assign
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors occurred: E0594, E0596.
-For more information about an error, try `rustc --explain E0594`.
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr b/src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr
index 0674c823016..ece3c62e6a9 100644
--- a/src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr
+++ b/src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `b` as mutable
+error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
   --> $DIR/mut-borrow-of-mut-ref.rs:18:7
    |
 LL | fn f(b: &mut i32) {
diff --git a/src/test/ui/borrowck/mutability-errors.nll.stderr b/src/test/ui/borrowck/mutability-errors.nll.stderr
new file mode 100644
index 00000000000..14c41bb81b2
--- /dev/null
+++ b/src/test/ui/borrowck/mutability-errors.nll.stderr
@@ -0,0 +1,379 @@
+error[E0594]: cannot assign to `*x` which is behind a `&` reference
+  --> $DIR/mutability-errors.rs:19:5
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- help: consider changing this to be a mutable reference: `&mut (i32,)`
+LL |     *x = (1,); //~ ERROR
+   |     ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `x.0` which is behind a `&` reference
+  --> $DIR/mutability-errors.rs:20:5
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- help: consider changing this to be a mutable reference: `&mut (i32,)`
+LL |     *x = (1,); //~ ERROR
+LL |     x.0 = 1; //~ ERROR
+   |     ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
+  --> $DIR/mutability-errors.rs:21:5
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- help: consider changing this to be a mutable reference: `&mut (i32,)`
+...
+LL |     &mut *x; //~ ERROR
+   |     ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `x.0` as mutable, as it is behind a `&` reference
+  --> $DIR/mutability-errors.rs:22:5
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- help: consider changing this to be a mutable reference: `&mut (i32,)`
+...
+LL |     &mut x.0; //~ ERROR
+   |     ^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/mutability-errors.rs:26:5
+   |
+LL |     *f() = (1,); //~ ERROR
+   |     ^^^^^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/mutability-errors.rs:27:5
+   |
+LL |     f().0 = 1; //~ ERROR
+   |     ^^^^^^^^^ cannot assign
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mutability-errors.rs:28:5
+   |
+LL |     &mut *f(); //~ ERROR
+   |     ^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mutability-errors.rs:29:5
+   |
+LL |     &mut f().0; //~ ERROR
+   |     ^^^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to `*x` which is behind a `*const` pointer
+  --> $DIR/mutability-errors.rs:33:5
+   |
+LL | unsafe fn named_ptr(x: *const (i32,)) {
+   |                        ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)`
+LL |     *x = (1,); //~ ERROR
+   |     ^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `x.0` which is behind a `*const` pointer
+  --> $DIR/mutability-errors.rs:34:5
+   |
+LL | unsafe fn named_ptr(x: *const (i32,)) {
+   |                        ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)`
+LL |     *x = (1,); //~ ERROR
+LL |     (*x).0 = 1; //~ ERROR
+   |     ^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written
+
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer
+  --> $DIR/mutability-errors.rs:35:5
+   |
+LL | unsafe fn named_ptr(x: *const (i32,)) {
+   |                        ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)`
+...
+LL |     &mut *x; //~ ERROR
+   |     ^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable
+
+error[E0596]: cannot borrow `x.0` as mutable, as it is behind a `*const` pointer
+  --> $DIR/mutability-errors.rs:36:5
+   |
+LL | unsafe fn named_ptr(x: *const (i32,)) {
+   |                        ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)`
+...
+LL |     &mut (*x).0; //~ ERROR
+   |     ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable
+
+error[E0594]: cannot assign to data in a `*const` pointer
+  --> $DIR/mutability-errors.rs:40:5
+   |
+LL |     *f() = (1,); //~ ERROR
+   |     ^^^^^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to data in a `*const` pointer
+  --> $DIR/mutability-errors.rs:41:5
+   |
+LL |     (*f()).0 = 1; //~ ERROR
+   |     ^^^^^^^^^^^^ cannot assign
+
+error[E0596]: cannot borrow data in a `*const` pointer as mutable
+  --> $DIR/mutability-errors.rs:42:5
+   |
+LL |     &mut *f(); //~ ERROR
+   |     ^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `*const` pointer as mutable
+  --> $DIR/mutability-errors.rs:43:5
+   |
+LL |     &mut (*f()).0; //~ ERROR
+   |     ^^^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
+  --> $DIR/mutability-errors.rs:50:9
+   |
+LL |         x = (1,); //~ ERROR
+   |         ^^^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:49:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,); //~ ERROR
+LL | |         x.0 = 1; //~ ERROR
+LL | |         &mut x; //~ ERROR
+LL | |         &mut x.0; //~ ERROR
+LL | |     });
+   | |_____^
+
+error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables
+  --> $DIR/mutability-errors.rs:51:9
+   |
+LL |         x.0 = 1; //~ ERROR
+   |         ^^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:49:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,); //~ ERROR
+LL | |         x.0 = 1; //~ ERROR
+LL | |         &mut x; //~ ERROR
+LL | |         &mut x.0; //~ ERROR
+LL | |     });
+   | |_____^
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/mutability-errors.rs:52:9
+   |
+LL |         &mut x; //~ ERROR
+   |         ^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:49:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,); //~ ERROR
+LL | |         x.0 = 1; //~ ERROR
+LL | |         &mut x; //~ ERROR
+LL | |         &mut x.0; //~ ERROR
+LL | |     });
+   | |_____^
+
+error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables
+  --> $DIR/mutability-errors.rs:53:9
+   |
+LL |         &mut x.0; //~ ERROR
+   |         ^^^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:49:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,); //~ ERROR
+LL | |         x.0 = 1; //~ ERROR
+LL | |         &mut x; //~ ERROR
+LL | |         &mut x.0; //~ ERROR
+LL | |     });
+   | |_____^
+
+error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
+  --> $DIR/mutability-errors.rs:56:9
+   |
+LL |         x = (1,); //~ ERROR
+   |         ^^^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:55:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         x = (1,); //~ ERROR
+LL | |         x.0 = 1; //~ ERROR
+LL | |         &mut x; //~ ERROR
+LL | |         &mut x.0; //~ ERROR
+LL | |     });
+   | |_____^
+
+error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables
+  --> $DIR/mutability-errors.rs:57:9
+   |
+LL |         x.0 = 1; //~ ERROR
+   |         ^^^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:55:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         x = (1,); //~ ERROR
+LL | |         x.0 = 1; //~ ERROR
+LL | |         &mut x; //~ ERROR
+LL | |         &mut x.0; //~ ERROR
+LL | |     });
+   | |_____^
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/mutability-errors.rs:58:9
+   |
+LL |         &mut x; //~ ERROR
+   |         ^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:55:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         x = (1,); //~ ERROR
+LL | |         x.0 = 1; //~ ERROR
+LL | |         &mut x; //~ ERROR
+LL | |         &mut x.0; //~ ERROR
+LL | |     });
+   | |_____^
+
+error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables
+  --> $DIR/mutability-errors.rs:59:9
+   |
+LL |         &mut x.0; //~ ERROR
+   |         ^^^^^^^^ cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/mutability-errors.rs:55:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         x = (1,); //~ ERROR
+LL | |         x.0 = 1; //~ ERROR
+LL | |         &mut x; //~ ERROR
+LL | |         &mut x.0; //~ ERROR
+LL | |     });
+   | |_____^
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/mutability-errors.rs:64:5
+   |
+LL | fn imm_local(x: (i32,)) {
+   |              - help: consider changing this to be mutable: `mut x`
+LL |     &mut x; //~ ERROR
+   |     ^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
+  --> $DIR/mutability-errors.rs:65:5
+   |
+LL | fn imm_local(x: (i32,)) {
+   |              - help: consider changing this to be mutable: `mut x`
+LL |     &mut x; //~ ERROR
+LL |     &mut x.0; //~ ERROR
+   |     ^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/mutability-errors.rs:70:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+LL |     || { //~ ERROR
+LL |         x = (1,);
+   |         ^^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
+  --> $DIR/mutability-errors.rs:71:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |         x.0 = 1;
+   |         ^^^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/mutability-errors.rs:72:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |         &mut x;
+   |         ^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
+  --> $DIR/mutability-errors.rs:73:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |         &mut x.0;
+   |         ^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/mutability-errors.rs:76:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |         x = (1,); //~ ERROR
+   |         ^^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
+  --> $DIR/mutability-errors.rs:77:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |         x.0 = 1; //~ ERROR
+   |         ^^^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+  --> $DIR/mutability-errors.rs:78:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |         &mut x; //~ ERROR
+   |         ^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
+  --> $DIR/mutability-errors.rs:79:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |         &mut x.0; //~ ERROR
+   |         ^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to immutable static item `X`
+  --> $DIR/mutability-errors.rs:86:5
+   |
+LL |     X = (1,); //~ ERROR
+   |     ^^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `X.0`, as `X` is an immutable static item
+  --> $DIR/mutability-errors.rs:87:5
+   |
+LL |     X.0 = 1; //~ ERROR
+   |     ^^^^^^^ cannot assign
+
+error[E0596]: cannot borrow immutable static item `X` as mutable
+  --> $DIR/mutability-errors.rs:88:5
+   |
+LL |     &mut X; //~ ERROR
+   |     ^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `X.0` as mutable, as `X` is an immutable static item
+  --> $DIR/mutability-errors.rs:89:5
+   |
+LL |     &mut X.0; //~ ERROR
+   |     ^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 38 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/mutability-errors.rs b/src/test/ui/borrowck/mutability-errors.rs
new file mode 100644
index 00000000000..0b4548cbebb
--- /dev/null
+++ b/src/test/ui/borrowck/mutability-errors.rs
@@ -0,0 +1,92 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// All the possible mutability error cases.
+
+#![allow(unused)]
+
+type MakeRef = fn() -> &'static (i32,);
+type MakePtr = fn() -> *const (i32,);
+
+fn named_ref(x: &(i32,)) {
+    *x = (1,); //~ ERROR
+    x.0 = 1; //~ ERROR
+    &mut *x; //~ ERROR
+    &mut x.0; //~ ERROR
+}
+
+fn unnamed_ref(f: MakeRef) {
+    *f() = (1,); //~ ERROR
+    f().0 = 1; //~ ERROR
+    &mut *f(); //~ ERROR
+    &mut f().0; //~ ERROR
+}
+
+unsafe fn named_ptr(x: *const (i32,)) {
+    *x = (1,); //~ ERROR
+    (*x).0 = 1; //~ ERROR
+    &mut *x; //~ ERROR
+    &mut (*x).0; //~ ERROR
+}
+
+unsafe fn unnamed_ptr(f: MakePtr) {
+    *f() = (1,); //~ ERROR
+    (*f()).0 = 1; //~ ERROR
+    &mut *f(); //~ ERROR
+    &mut (*f()).0; //~ ERROR
+}
+
+fn fn_ref<F: Fn()>(f: F) -> F { f }
+
+fn ref_closure(mut x: (i32,)) {
+    fn_ref(|| {
+        x = (1,); //~ ERROR
+        x.0 = 1; //~ ERROR
+        &mut x; //~ ERROR
+        &mut x.0; //~ ERROR
+    });
+    fn_ref(move || {
+        x = (1,); //~ ERROR
+        x.0 = 1; //~ ERROR
+        &mut x; //~ ERROR
+        &mut x.0; //~ ERROR
+    });
+}
+
+fn imm_local(x: (i32,)) {
+    &mut x; //~ ERROR
+    &mut x.0; //~ ERROR
+}
+
+fn imm_capture(x: (i32,)) {
+    || { //~ ERROR
+        x = (1,);
+        x.0 = 1;
+        &mut x;
+        &mut x.0;
+    };
+    move || {
+        x = (1,); //~ ERROR
+        x.0 = 1; //~ ERROR
+        &mut x; //~ ERROR
+        &mut x.0; //~ ERROR
+    };
+}
+
+static X: (i32,) = (0,);
+
+fn imm_static() {
+    X = (1,); //~ ERROR
+    X.0 = 1; //~ ERROR
+    &mut X; //~ ERROR
+    &mut X.0; //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/mutability-errors.stderr b/src/test/ui/borrowck/mutability-errors.stderr
new file mode 100644
index 00000000000..d77254f3141
--- /dev/null
+++ b/src/test/ui/borrowck/mutability-errors.stderr
@@ -0,0 +1,308 @@
+error[E0594]: cannot assign to immutable borrowed content `*x`
+  --> $DIR/mutability-errors.rs:19:5
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- use `&mut (i32,)` here to make mutable
+LL |     *x = (1,); //~ ERROR
+   |     ^^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to field `x.0` of immutable binding
+  --> $DIR/mutability-errors.rs:20:5
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- use `&mut (i32,)` here to make mutable
+LL |     *x = (1,); //~ ERROR
+LL |     x.0 = 1; //~ ERROR
+   |     ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
+  --> $DIR/mutability-errors.rs:21:10
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- use `&mut (i32,)` here to make mutable
+...
+LL |     &mut *x; //~ ERROR
+   |          ^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:22:10
+   |
+LL | fn named_ref(x: &(i32,)) {
+   |                 ------- use `&mut (i32,)` here to make mutable
+...
+LL |     &mut x.0; //~ ERROR
+   |          ^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to immutable borrowed content
+  --> $DIR/mutability-errors.rs:26:5
+   |
+LL |     *f() = (1,); //~ ERROR
+   |     ^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to field of immutable binding
+  --> $DIR/mutability-errors.rs:27:5
+   |
+LL |     f().0 = 1; //~ ERROR
+   |     ^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow immutable borrowed content as mutable
+  --> $DIR/mutability-errors.rs:28:10
+   |
+LL |     &mut *f(); //~ ERROR
+   |          ^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow field of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:29:10
+   |
+LL |     &mut f().0; //~ ERROR
+   |          ^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to immutable dereference of raw pointer `*x`
+  --> $DIR/mutability-errors.rs:33:5
+   |
+LL |     *x = (1,); //~ ERROR
+   |     ^^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to field `x.0` of immutable binding
+  --> $DIR/mutability-errors.rs:34:5
+   |
+LL |     (*x).0 = 1; //~ ERROR
+   |     ^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow immutable dereference of raw pointer `*x` as mutable
+  --> $DIR/mutability-errors.rs:35:10
+   |
+LL |     &mut *x; //~ ERROR
+   |          ^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:36:10
+   |
+LL |     &mut (*x).0; //~ ERROR
+   |          ^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to immutable dereference of raw pointer
+  --> $DIR/mutability-errors.rs:40:5
+   |
+LL |     *f() = (1,); //~ ERROR
+   |     ^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0594]: cannot assign to field of immutable binding
+  --> $DIR/mutability-errors.rs:41:5
+   |
+LL |     (*f()).0 = 1; //~ ERROR
+   |     ^^^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow immutable dereference of raw pointer as mutable
+  --> $DIR/mutability-errors.rs:42:10
+   |
+LL |     &mut *f(); //~ ERROR
+   |          ^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow field of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:43:10
+   |
+LL |     &mut (*f()).0; //~ ERROR
+   |          ^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0387]: cannot assign to data in a captured outer variable in an `Fn` closure
+  --> $DIR/mutability-errors.rs:50:9
+   |
+LL |         x = (1,); //~ ERROR
+   |         ^^^^^^^^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/mutability-errors.rs:49:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,); //~ ERROR
+LL | |         x.0 = 1; //~ ERROR
+LL | |         &mut x; //~ ERROR
+LL | |         &mut x.0; //~ ERROR
+LL | |     });
+   | |_____^
+
+error[E0387]: cannot assign to data in a captured outer variable in an `Fn` closure
+  --> $DIR/mutability-errors.rs:51:9
+   |
+LL |         x.0 = 1; //~ ERROR
+   |         ^^^^^^^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/mutability-errors.rs:49:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,); //~ ERROR
+LL | |         x.0 = 1; //~ ERROR
+LL | |         &mut x; //~ ERROR
+LL | |         &mut x.0; //~ ERROR
+LL | |     });
+   | |_____^
+
+error[E0387]: cannot borrow data mutably in a captured outer variable in an `Fn` closure
+  --> $DIR/mutability-errors.rs:52:14
+   |
+LL |         &mut x; //~ ERROR
+   |              ^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/mutability-errors.rs:49:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,); //~ ERROR
+LL | |         x.0 = 1; //~ ERROR
+LL | |         &mut x; //~ ERROR
+LL | |         &mut x.0; //~ ERROR
+LL | |     });
+   | |_____^
+
+error[E0387]: cannot borrow data mutably in a captured outer variable in an `Fn` closure
+  --> $DIR/mutability-errors.rs:53:14
+   |
+LL |         &mut x.0; //~ ERROR
+   |              ^^^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/mutability-errors.rs:49:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         x = (1,); //~ ERROR
+LL | |         x.0 = 1; //~ ERROR
+LL | |         &mut x; //~ ERROR
+LL | |         &mut x.0; //~ ERROR
+LL | |     });
+   | |_____^
+
+error[E0594]: cannot assign to captured outer variable in an `Fn` closure
+  --> $DIR/mutability-errors.rs:56:9
+   |
+LL |         x = (1,); //~ ERROR
+   |         ^^^^^^^^
+   |
+   = note: `Fn` closures cannot capture their enclosing environment for modifications
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/mutability-errors.rs:55:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         x = (1,); //~ ERROR
+LL | |         x.0 = 1; //~ ERROR
+LL | |         &mut x; //~ ERROR
+LL | |         &mut x.0; //~ ERROR
+LL | |     });
+   | |_____^
+
+error[E0594]: cannot assign to field `x.0` of immutable binding
+  --> $DIR/mutability-errors.rs:57:9
+   |
+LL |         x.0 = 1; //~ ERROR
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow captured outer variable in an `Fn` closure as mutable
+  --> $DIR/mutability-errors.rs:58:14
+   |
+LL |         &mut x; //~ ERROR
+   |              ^
+   |
+help: consider changing this closure to take self by mutable reference
+  --> $DIR/mutability-errors.rs:55:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         x = (1,); //~ ERROR
+LL | |         x.0 = 1; //~ ERROR
+LL | |         &mut x; //~ ERROR
+LL | |         &mut x.0; //~ ERROR
+LL | |     });
+   | |_____^
+
+error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:59:14
+   |
+LL |         &mut x.0; //~ ERROR
+   |              ^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow immutable argument `x` as mutable
+  --> $DIR/mutability-errors.rs:64:10
+   |
+LL | fn imm_local(x: (i32,)) {
+   |              - consider changing this to `mut x`
+LL |     &mut x; //~ ERROR
+   |          ^ cannot borrow mutably
+
+error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:65:10
+   |
+LL | fn imm_local(x: (i32,)) {
+   |              - consider changing this to `mut x`
+LL |     &mut x; //~ ERROR
+LL |     &mut x.0; //~ ERROR
+   |          ^^^ cannot mutably borrow field of immutable binding
+
+error[E0595]: closure cannot assign to immutable argument `x`
+  --> $DIR/mutability-errors.rs:69:5
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - consider changing this to `mut x`
+LL |     || { //~ ERROR
+   |     ^^ cannot borrow mutably
+
+error[E0594]: cannot assign to captured outer variable in an `FnMut` closure
+  --> $DIR/mutability-errors.rs:76:9
+   |
+LL | fn imm_capture(x: (i32,)) {
+   |                - help: consider making `x` mutable: `mut x`
+...
+LL |         x = (1,); //~ ERROR
+   |         ^^^^^^^^
+
+error[E0594]: cannot assign to field `x.0` of immutable binding
+  --> $DIR/mutability-errors.rs:77:9
+   |
+LL |         x.0 = 1; //~ ERROR
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow captured outer variable in an `FnMut` closure as mutable
+  --> $DIR/mutability-errors.rs:78:14
+   |
+LL |         &mut x; //~ ERROR
+   |              ^
+
+error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:79:14
+   |
+LL |         &mut x.0; //~ ERROR
+   |              ^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to immutable static item
+  --> $DIR/mutability-errors.rs:86:5
+   |
+LL |     X = (1,); //~ ERROR
+   |     ^^^^^^^^
+
+error[E0594]: cannot assign to field of immutable binding
+  --> $DIR/mutability-errors.rs:87:5
+   |
+LL |     X.0 = 1; //~ ERROR
+   |     ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0596]: cannot borrow immutable static item as mutable
+  --> $DIR/mutability-errors.rs:88:10
+   |
+LL |     &mut X; //~ ERROR
+   |          ^
+
+error[E0596]: cannot borrow field of immutable binding as mutable
+  --> $DIR/mutability-errors.rs:89:10
+   |
+LL |     &mut X.0; //~ ERROR
+   |          ^^^ cannot mutably borrow field of immutable binding
+
+error: aborting due to 35 previous errors
+
+Some errors occurred: E0387, E0594, E0595, E0596.
+For more information about an error, try `rustc --explain E0387`.
diff --git a/src/test/ui/closure-immutable-outer-variable.nll.stderr b/src/test/ui/closure-immutable-outer-variable.nll.stderr
index 335ccefe8a0..d91c1199b3f 100644
--- a/src/test/ui/closure-immutable-outer-variable.nll.stderr
+++ b/src/test/ui/closure-immutable-outer-variable.nll.stderr
@@ -1,6 +1,8 @@
-error[E0594]: cannot assign to immutable item `y`
+error[E0594]: cannot assign to `y`, as it is not declared as mutable
   --> $DIR/closure-immutable-outer-variable.rs:21:26
    |
+LL |     let y = true;
+   |         - help: consider changing this to be mutable: `mut y`
 LL |     foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable
    |                          ^^^^^^^^^ cannot assign
 
diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr b/src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr
index da0b201f5d4..8251f04d353 100644
--- a/src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr
+++ b/src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `x` as mutable
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
   --> $DIR/huge_multispan_highlight.rs:100:13
    |
 LL |     let x = "foo";
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 21c5e3608c0..eae834e2b1a 100644
--- a/src/test/ui/did_you_mean/issue-31424.nll.stderr
+++ b/src/test/ui/did_you_mean/issue-31424.nll.stderr
@@ -1,10 +1,10 @@
-error[E0596]: cannot borrow immutable item `self` as mutable
+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
 
-error[E0596]: cannot borrow immutable item `self` as mutable
+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) {
diff --git a/src/test/ui/did_you_mean/issue-34126.nll.stderr b/src/test/ui/did_you_mean/issue-34126.nll.stderr
index 8dedb6ec4db..004c43a7343 100644
--- a/src/test/ui/did_you_mean/issue-34126.nll.stderr
+++ b/src/test/ui/did_you_mean/issue-34126.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `self` as mutable
+error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
   --> $DIR/issue-34126.rs:16:18
    |
 LL |         self.run(&mut self); //~ ERROR cannot borrow
diff --git a/src/test/ui/did_you_mean/issue-34337.nll.stderr b/src/test/ui/did_you_mean/issue-34337.nll.stderr
index d2271e8e7de..38315a067c0 100644
--- a/src/test/ui/did_you_mean/issue-34337.nll.stderr
+++ b/src/test/ui/did_you_mean/issue-34337.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `key` as mutable
+error[E0596]: cannot borrow `key` as mutable, as it is not declared as mutable
   --> $DIR/issue-34337.rs:16:9
    |
 LL |     get(&mut key); //~ ERROR cannot borrow
diff --git a/src/test/ui/did_you_mean/issue-35937.nll.stderr b/src/test/ui/did_you_mean/issue-35937.nll.stderr
index 7eaa4c7d5fe..804e5f0531f 100644
--- a/src/test/ui/did_you_mean/issue-35937.nll.stderr
+++ b/src/test/ui/did_you_mean/issue-35937.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `f.v` as mutable
+error[E0596]: cannot borrow `f.v` as mutable, as `f` is not declared as mutable
   --> $DIR/issue-35937.rs:17:5
    |
 LL |     let f = Foo { v: Vec::new() };
diff --git a/src/test/ui/did_you_mean/issue-37139.nll.stderr b/src/test/ui/did_you_mean/issue-37139.nll.stderr
index e51a1baad25..7cc7ca14638 100644
--- a/src/test/ui/did_you_mean/issue-37139.nll.stderr
+++ b/src/test/ui/did_you_mean/issue-37139.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `x` as mutable
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
   --> $DIR/issue-37139.rs:22:18
    |
 LL |             test(&mut x); //~ ERROR cannot borrow immutable
diff --git a/src/test/ui/did_you_mean/issue-38147-1.nll.stderr b/src/test/ui/did_you_mean/issue-38147-1.nll.stderr
index d156d64b9d6..25613561bba 100644
--- a/src/test/ui/did_you_mean/issue-38147-1.nll.stderr
+++ b/src/test/ui/did_you_mean/issue-38147-1.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `*self.s` as mutable
+error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
   --> $DIR/issue-38147-1.rs:27:9
    |
 LL |     fn f(&self) {
diff --git a/src/test/ui/did_you_mean/issue-38147-2.nll.stderr b/src/test/ui/did_you_mean/issue-38147-2.nll.stderr
index c8e231ea3b3..21fc4079d5b 100644
--- a/src/test/ui/did_you_mean/issue-38147-2.nll.stderr
+++ b/src/test/ui/did_you_mean/issue-38147-2.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `*self.s` as mutable
+error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
   --> $DIR/issue-38147-2.rs:17:9
    |
 LL |         self.s.push('x');
diff --git a/src/test/ui/did_you_mean/issue-38147-3.nll.stderr b/src/test/ui/did_you_mean/issue-38147-3.nll.stderr
index c5d6551b647..d426c1f37fc 100644
--- a/src/test/ui/did_you_mean/issue-38147-3.nll.stderr
+++ b/src/test/ui/did_you_mean/issue-38147-3.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `*self.s` as mutable
+error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
   --> $DIR/issue-38147-3.rs:17:9
    |
 LL |         self.s.push('x');
diff --git a/src/test/ui/did_you_mean/issue-38147-4.nll.stderr b/src/test/ui/did_you_mean/issue-38147-4.nll.stderr
index c875957623b..eccbe19ac94 100644
--- a/src/test/ui/did_you_mean/issue-38147-4.nll.stderr
+++ b/src/test/ui/did_you_mean/issue-38147-4.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `*f.s` as mutable
+error[E0596]: cannot borrow `*f.s` as mutable, as it is behind a `&` reference
   --> $DIR/issue-38147-4.rs:16:5
    |
 LL | fn f(x: usize, f: &Foo) {
diff --git a/src/test/ui/did_you_mean/issue-39544.nll.stderr b/src/test/ui/did_you_mean/issue-39544.nll.stderr
index e2d2fcd63db..00e4cc6b0c3 100644
--- a/src/test/ui/did_you_mean/issue-39544.nll.stderr
+++ b/src/test/ui/did_you_mean/issue-39544.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `z.x` as mutable
+error[E0596]: cannot borrow `z.x` as mutable, as `z` is not declared as mutable
   --> $DIR/issue-39544.rs:21:13
    |
 LL |     let z = Z { x: X::Y };
@@ -6,7 +6,7 @@ LL |     let z = Z { x: X::Y };
 LL |     let _ = &mut z.x; //~ ERROR cannot borrow
    |             ^^^^^^^^ cannot borrow as mutable
 
-error[E0596]: cannot borrow immutable item `self.x` as mutable
+error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:26:17
    |
 LL |     fn foo<'z>(&'z self) {
@@ -14,7 +14,7 @@ LL |     fn foo<'z>(&'z self) {
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `self.x` as mutable
+error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:30:17
    |
 LL |     fn foo1(&self, other: &Z) {
@@ -22,7 +22,7 @@ LL |     fn foo1(&self, other: &Z) {
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `other.x` as mutable
+error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:31:17
    |
 LL |     fn foo1(&self, other: &Z) {
@@ -31,7 +31,7 @@ LL |         let _ = &mut self.x; //~ ERROR cannot borrow
 LL |         let _ = &mut other.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `self.x` as mutable
+error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:35:17
    |
 LL |     fn foo2<'a>(&'a self, other: &Z) {
@@ -39,7 +39,7 @@ LL |     fn foo2<'a>(&'a self, other: &Z) {
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `other.x` as mutable
+error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:36:17
    |
 LL |     fn foo2<'a>(&'a self, other: &Z) {
@@ -48,7 +48,7 @@ LL |         let _ = &mut self.x; //~ ERROR cannot borrow
 LL |         let _ = &mut other.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `self.x` as mutable
+error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:40:17
    |
 LL |     fn foo3<'a>(self: &'a Self, other: &Z) {
@@ -56,7 +56,7 @@ LL |     fn foo3<'a>(self: &'a Self, other: &Z) {
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `other.x` as mutable
+error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:41:17
    |
 LL |     fn foo3<'a>(self: &'a Self, other: &Z) {
@@ -65,7 +65,7 @@ LL |         let _ = &mut self.x; //~ ERROR cannot borrow
 LL |         let _ = &mut other.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `other.x` as mutable
+error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:45:17
    |
 LL |     fn foo4(other: &Z) {
@@ -73,7 +73,7 @@ LL |     fn foo4(other: &Z) {
 LL |         let _ = &mut other.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `z.x` as mutable
+error[E0596]: cannot borrow `z.x` as mutable, as `z` is not declared as mutable
   --> $DIR/issue-39544.rs:51:13
    |
 LL | pub fn with_arg(z: Z, w: &Z) {
@@ -81,7 +81,7 @@ LL | pub fn with_arg(z: Z, w: &Z) {
 LL |     let _ = &mut z.x; //~ ERROR cannot borrow
    |             ^^^^^^^^ cannot borrow as mutable
 
-error[E0596]: cannot borrow immutable item `w.x` as mutable
+error[E0596]: cannot borrow `w.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:52:13
    |
 LL | pub fn with_arg(z: Z, w: &Z) {
diff --git a/src/test/ui/did_you_mean/issue-40823.nll.stderr b/src/test/ui/did_you_mean/issue-40823.nll.stderr
index 1fd75de8128..44ae058cc28 100644
--- a/src/test/ui/did_you_mean/issue-40823.nll.stderr
+++ b/src/test/ui/did_you_mean/issue-40823.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `*buf` as mutable
+error[E0596]: cannot borrow `*buf` as mutable, as it is behind a `&` reference
   --> $DIR/issue-40823.rs:13:5
    |
 LL |     let mut buf = &[1, 2, 3, 4];
diff --git a/src/test/ui/error-codes/E0017.nll.stderr b/src/test/ui/error-codes/E0017.nll.stderr
index addbbf4434f..08708d213d3 100644
--- a/src/test/ui/error-codes/E0017.nll.stderr
+++ b/src/test/ui/error-codes/E0017.nll.stderr
@@ -10,7 +10,7 @@ error[E0017]: references in statics may only refer to immutable values
 LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
    |                                       ^^^^^^ statics require immutable values
 
-error[E0596]: cannot borrow immutable item `X` as mutable
+error[E0596]: cannot borrow immutable static item `X` as mutable
   --> $DIR/E0017.rs:15:39
    |
 LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
diff --git a/src/test/ui/error-codes/E0388.nll.stderr b/src/test/ui/error-codes/E0388.nll.stderr
index 0238ca6b623..a048374a497 100644
--- a/src/test/ui/error-codes/E0388.nll.stderr
+++ b/src/test/ui/error-codes/E0388.nll.stderr
@@ -10,7 +10,7 @@ error[E0017]: references in statics may only refer to immutable values
 LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
    |                                       ^^^^^^ statics require immutable values
 
-error[E0596]: cannot borrow immutable item `X` as mutable
+error[E0596]: cannot borrow immutable static item `X` as mutable
   --> $DIR/E0388.rs:15:39
    |
 LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
diff --git a/src/test/ui/fn-closure-mutable-capture.nll.stderr b/src/test/ui/fn-closure-mutable-capture.nll.stderr
index 7ef21d3720d..ff06256088f 100644
--- a/src/test/ui/fn-closure-mutable-capture.nll.stderr
+++ b/src/test/ui/fn-closure-mutable-capture.nll.stderr
@@ -1,8 +1,14 @@
-error[E0594]: cannot assign to `x` which is behind a `&` reference
+error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
   --> $DIR/fn-closure-mutable-capture.rs:15:17
    |
 LL |     bar(move || x = 1);
    |                 ^^^^^ cannot assign
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/fn-closure-mutable-capture.rs:15:9
+   |
+LL |     bar(move || x = 1);
+   |         ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issue-21600.nll.stderr b/src/test/ui/issue-21600.nll.stderr
index b5b9cefb706..5fe8dc45ccc 100644
--- a/src/test/ui/issue-21600.nll.stderr
+++ b/src/test/ui/issue-21600.nll.stderr
@@ -1,14 +1,33 @@
-error[E0596]: cannot borrow immutable item `x` as mutable
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
   --> $DIR/issue-21600.rs:24:20
    |
 LL |         call_it(|| x.gen_mut()); //~ ERROR cannot borrow data mutably in a captured outer
    |                    ^ cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/issue-21600.rs:24:17
+   |
+LL |         call_it(|| x.gen_mut()); //~ ERROR cannot borrow data mutably in a captured outer
+   |                 ^^^^^^^^^^^^^^
 
-error[E0596]: cannot borrow immutable item `x` as mutable
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
   --> $DIR/issue-21600.rs:24:17
    |
 LL |         call_it(|| x.gen_mut()); //~ ERROR cannot borrow data mutably in a captured outer
-   |                 ^^^^^^^^^^^^^^ cannot borrow as mutable
+   |                 ^^ - mutable borrow occurs due to use of `x` in closure
+   |                 |
+   |                 cannot borrow as mutable
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/issue-21600.rs:22:13
+   |
+LL |       call_it(|| {
+   |  _____________^
+LL | |         call_it(|| x.gen());
+LL | |         call_it(|| x.gen_mut()); //~ ERROR cannot borrow data mutably in a captured outer
+LL | |         //~^ ERROR cannot borrow data mutably in a captured outer
+LL | |     });
+   | |_____^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issue-27282-reborrow-ref-mut-in-guard.rs b/src/test/ui/issue-27282-reborrow-ref-mut-in-guard.rs
index 5d445c63ef4..39d54f6e7ae 100644
--- a/src/test/ui/issue-27282-reborrow-ref-mut-in-guard.rs
+++ b/src/test/ui/issue-27282-reborrow-ref-mut-in-guard.rs
@@ -24,7 +24,7 @@ fn main() {
     match b {
         &mut false => {},
         ref mut r if { (|| { let bar = &mut *r; **bar = false; })();
-                             //~^ ERROR cannot borrow immutable item `*r` as mutable
+        //~^ ERROR cannot borrow `r` as mutable, as it is immutable for the pattern guard
                              false } => { &mut *r; },
         &mut true => { println!("You might think we should get here"); },
         _ => panic!("surely we could never get here, since rustc warns it is unreachable."),
diff --git a/src/test/ui/issue-27282-reborrow-ref-mut-in-guard.stderr b/src/test/ui/issue-27282-reborrow-ref-mut-in-guard.stderr
index d767fdde9f2..660902880ac 100644
--- a/src/test/ui/issue-27282-reborrow-ref-mut-in-guard.stderr
+++ b/src/test/ui/issue-27282-reborrow-ref-mut-in-guard.stderr
@@ -1,8 +1,12 @@
-error[E0596]: cannot borrow immutable item `*r` as mutable
-  --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:26:24
+error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard
+  --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:26:25
    |
 LL |         ref mut r if { (|| { let bar = &mut *r; **bar = false; })();
-   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
+   |                         ^^                   - mutable borrow occurs due to use of `r` in closure
+   |                         |
+   |                         cannot borrow as mutable
+   |
+   = note: variables bound in patterns are immutable until the end of the pattern guard
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issue-33819.nll.stderr b/src/test/ui/issue-33819.nll.stderr
index 88728207921..78ad31a04c8 100644
--- a/src/test/ui/issue-33819.nll.stderr
+++ b/src/test/ui/issue-33819.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `v` as mutable
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
   --> $DIR/issue-33819.rs:13:34
    |
 LL |         Some(ref v) => { let a = &mut v; },
diff --git a/src/test/ui/issue-36400.nll.stderr b/src/test/ui/issue-36400.nll.stderr
index be10b1d517b..e4347f0ece8 100644
--- a/src/test/ui/issue-36400.nll.stderr
+++ b/src/test/ui/issue-36400.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `*x` as mutable
+error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable
   --> $DIR/issue-36400.rs:15:7
    |
 LL |     let x = Box::new(3);
diff --git a/src/test/ui/issue-41726.nll.stderr b/src/test/ui/issue-41726.nll.stderr
index feeb63e1ebb..06ff743a0f5 100644
--- a/src/test/ui/issue-41726.nll.stderr
+++ b/src/test/ui/issue-41726.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item as mutable
+error[E0596]: cannot borrow data in a `&` reference as mutable
   --> $DIR/issue-41726.rs:15:9
    |
 LL |         things[src.as_str()].sort(); //~ ERROR cannot borrow immutable
diff --git a/src/test/ui/issue-42344.nll.stderr b/src/test/ui/issue-42344.nll.stderr
index 02f6ffe1734..1abc448dbb0 100644
--- a/src/test/ui/issue-42344.nll.stderr
+++ b/src/test/ui/issue-42344.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `*TAB[..]` as mutable
+error[E0596]: cannot borrow `*TAB[..]` as mutable, as `TAB` is an immutable static item
   --> $DIR/issue-42344.rs:14:5
    |
 LL |     TAB[0].iter_mut(); //~ ERROR cannot borrow data mutably in a `&` reference [E0389]
diff --git a/src/test/ui/issue-46023.ast.nll.stderr b/src/test/ui/issue-46023.ast.nll.stderr
index 2fc2924c2ec..bda629d48af 100644
--- a/src/test/ui/issue-46023.ast.nll.stderr
+++ b/src/test/ui/issue-46023.ast.nll.stderr
@@ -1,6 +1,9 @@
-error[E0594]: cannot assign to immutable item `x`
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
   --> $DIR/issue-46023.rs:18:9
    |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+...
 LL |         x = 1;
    |         ^^^^^ cannot assign
 
diff --git a/src/test/ui/issue-46023.mir.stderr b/src/test/ui/issue-46023.mir.stderr
index 2fc2924c2ec..bda629d48af 100644
--- a/src/test/ui/issue-46023.mir.stderr
+++ b/src/test/ui/issue-46023.mir.stderr
@@ -1,6 +1,9 @@
-error[E0594]: cannot assign to immutable item `x`
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
   --> $DIR/issue-46023.rs:18:9
    |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+...
 LL |         x = 1;
    |         ^^^^^ cannot assign
 
diff --git a/src/test/ui/issue-46023.rs b/src/test/ui/issue-46023.rs
index d51d92570fd..d5c8cd6d0f8 100644
--- a/src/test/ui/issue-46023.rs
+++ b/src/test/ui/issue-46023.rs
@@ -16,7 +16,7 @@ fn main() {
 
     (move || {
         x = 1;
-        //[mir]~^ ERROR cannot assign to immutable item `x` [E0594]
+        //[mir]~^ ERROR cannot assign to `x`, as it is not declared as mutable [E0594]
         //[ast]~^^ ERROR cannot assign to captured outer variable in an `FnMut` closure [E0594]
     })()
 }
diff --git a/src/test/ui/issue-46604.ast.nll.stderr b/src/test/ui/issue-46604.ast.nll.stderr
index b947bec6397..a4ee0d4e2a3 100644
--- a/src/test/ui/issue-46604.ast.nll.stderr
+++ b/src/test/ui/issue-46604.ast.nll.stderr
@@ -4,7 +4,7 @@ error[E0017]: references in statics may only refer to immutable values
 LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];   //[ast]~ ERROR E0017
    |                         ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
 
-error[E0594]: cannot assign to immutable item `buf[..]`
+error[E0594]: cannot assign to `buf[..]`, as `buf` is an immutable static item
   --> $DIR/issue-46604.rs:20:5
    |
 LL |     buf[0]=2;                                   //[ast]~ ERROR E0389
diff --git a/src/test/ui/issue-46604.mir.stderr b/src/test/ui/issue-46604.mir.stderr
index b947bec6397..a4ee0d4e2a3 100644
--- a/src/test/ui/issue-46604.mir.stderr
+++ b/src/test/ui/issue-46604.mir.stderr
@@ -4,7 +4,7 @@ error[E0017]: references in statics may only refer to immutable values
 LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];   //[ast]~ ERROR E0017
    |                         ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
 
-error[E0594]: cannot assign to immutable item `buf[..]`
+error[E0594]: cannot assign to `buf[..]`, as `buf` is an immutable static item
   --> $DIR/issue-46604.rs:20:5
    |
 LL |     buf[0]=2;                                   //[ast]~ ERROR E0389
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr
index 01e26980323..d5bba6649a2 100644
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr
@@ -12,7 +12,7 @@ LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) {
 LL |   y.push(z); //~ ERROR lifetime mismatch
    |   ^ ...but data from `z` flows into `y` here
 
-error[E0596]: cannot borrow immutable item `y` as mutable
+error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
   --> $DIR/ex3-both-anon-regions-using-fn-items.rs:11:3
    |
 LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) {
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr
index a61d49fc953..0608b3be8b3 100644
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr
@@ -12,7 +12,7 @@ LL | fn foo(x:Box<Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
 LL |   y.push(z); //~ ERROR lifetime mismatch
    |   ^ ...but data from `z` flows into `y` here
 
-error[E0596]: cannot borrow immutable item `y` as mutable
+error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
   --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:11:3
    |
 LL | fn foo(x:Box<Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
diff --git a/src/test/ui/macros/span-covering-argument-1.nll.stderr b/src/test/ui/macros/span-covering-argument-1.nll.stderr
index 213eddee720..3947f6c0f11 100644
--- a/src/test/ui/macros/span-covering-argument-1.nll.stderr
+++ b/src/test/ui/macros/span-covering-argument-1.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `foo` as mutable
+error[E0596]: cannot borrow `foo` as mutable, as it is not declared as mutable
   --> $DIR/span-covering-argument-1.rs:15:14
    |
 LL |             let $s = 0;
diff --git a/src/test/ui/nll/closure-captures.rs b/src/test/ui/nll/closure-captures.rs
new file mode 100644
index 00000000000..03a22bb79a8
--- /dev/null
+++ b/src/test/ui/nll/closure-captures.rs
@@ -0,0 +1,68 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Some cases with closures that might be problems
+
+#![allow(unused)]
+#![feature(nll)]
+
+// Should have one error per assigment
+
+fn one_closure(x: i32) {
+    ||
+    x = 1; //~ ERROR
+    move ||
+    x = 1; //~ ERROR
+}
+
+fn two_closures(x: i32) {
+    || {
+        ||
+        x = 1; //~ ERROR
+    };
+    move || {
+        ||
+        x = 1; //~ ERROR
+    };
+}
+
+fn fn_ref<F: Fn()>(f: F) -> F { f }
+
+fn two_closures_ref_mut(mut x: i32) {
+    fn_ref(|| {
+        || //~ ERROR
+         x = 1;}
+    );
+    fn_ref(move || {
+        ||  //~ ERROR
+    x = 1;});
+}
+
+// This still gives two messages, but it requires two things to be fixed.
+fn two_closures_ref(x: i32) {
+    fn_ref(|| {
+        || //~ ERROR
+         x = 1;} //~ ERROR
+    );
+    fn_ref(move || {
+        ||  //~ ERROR
+    x = 1;}); //~ ERROR
+}
+
+fn two_closures_two_refs(x: &mut i32) {
+    fn_ref(|| {
+        || //~ ERROR
+        *x = 1;});
+    fn_ref(move || {
+        || //~ ERROR
+        *x = 1;});
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-captures.stderr b/src/test/ui/nll/closure-captures.stderr
new file mode 100644
index 00000000000..a03e104a1b1
--- /dev/null
+++ b/src/test/ui/nll/closure-captures.stderr
@@ -0,0 +1,160 @@
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/closure-captures.rs:20:5
+   |
+LL | fn one_closure(x: i32) {
+   |                - help: consider changing this to be mutable: `mut x`
+LL |     ||
+LL |     x = 1; //~ ERROR
+   |     ^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/closure-captures.rs:22:5
+   |
+LL | fn one_closure(x: i32) {
+   |                - help: consider changing this to be mutable: `mut x`
+...
+LL |     x = 1; //~ ERROR
+   |     ^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/closure-captures.rs:28:9
+   |
+LL | fn two_closures(x: i32) {
+   |                 - help: consider changing this to be mutable: `mut x`
+...
+LL |         x = 1; //~ ERROR
+   |         ^^^^^ cannot assign
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/closure-captures.rs:32:9
+   |
+LL | fn two_closures(x: i32) {
+   |                 - help: consider changing this to be mutable: `mut x`
+...
+LL |         x = 1; //~ ERROR
+   |         ^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/closure-captures.rs:40:9
+   |
+LL |         || //~ ERROR
+   |         ^^ cannot borrow as mutable
+LL |          x = 1;}
+   |          - mutable borrow occurs due to use of `x` in closure
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/closure-captures.rs:39:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         || //~ ERROR
+LL | |          x = 1;}
+   | |________________^
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/closure-captures.rs:44:9
+   |
+LL |         ||  //~ ERROR
+   |         ^^ cannot borrow as mutable
+LL |     x = 1;});
+   |     - mutable borrow occurs due to use of `x` in closure
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/closure-captures.rs:43:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         ||  //~ ERROR
+LL | |     x = 1;});
+   | |___________^
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/closure-captures.rs:52:10
+   |
+LL | fn two_closures_ref(x: i32) {
+   |                     - help: consider changing this to be mutable: `mut x`
+...
+LL |          x = 1;} //~ ERROR
+   |          ^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/closure-captures.rs:51:9
+   |
+LL |         || //~ ERROR
+   |         ^^ cannot borrow as mutable
+LL |          x = 1;} //~ ERROR
+   |          - mutable borrow occurs due to use of `x` in closure
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/closure-captures.rs:50:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         || //~ ERROR
+LL | |          x = 1;} //~ ERROR
+   | |________________^
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/closure-captures.rs:56:5
+   |
+LL | fn two_closures_ref(x: i32) {
+   |                     - help: consider changing this to be mutable: `mut x`
+...
+LL |     x = 1;}); //~ ERROR
+   |     ^^^^^ cannot assign
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/closure-captures.rs:55:9
+   |
+LL |         ||  //~ ERROR
+   |         ^^ cannot borrow as mutable
+LL |     x = 1;}); //~ ERROR
+   |     - mutable borrow occurs due to use of `x` in closure
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/closure-captures.rs:54:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         ||  //~ ERROR
+LL | |     x = 1;}); //~ ERROR
+   | |___________^
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/closure-captures.rs:61:9
+   |
+LL |         || //~ ERROR
+   |         ^^ cannot borrow as mutable
+LL |         *x = 1;});
+   |          - mutable borrow occurs due to use of `x` in closure
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/closure-captures.rs:60:12
+   |
+LL |       fn_ref(|| {
+   |  ____________^
+LL | |         || //~ ERROR
+LL | |         *x = 1;});
+   | |________________^
+
+error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
+  --> $DIR/closure-captures.rs:64:9
+   |
+LL |         || //~ ERROR
+   |         ^^ cannot borrow as mutable
+LL |         *x = 1;});
+   |          - mutable borrow occurs due to use of `x` in closure
+   |
+help: consider changing this to accept closures that implement `FnMut`
+  --> $DIR/closure-captures.rs:63:12
+   |
+LL |       fn_ref(move || {
+   |  ____________^
+LL | |         || //~ ERROR
+LL | |         *x = 1;});
+   | |________________^
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/nll/generator-upvar-mutability.stderr b/src/test/ui/nll/generator-upvar-mutability.stderr
index 9c5c57687a2..180a330a30e 100644
--- a/src/test/ui/nll/generator-upvar-mutability.stderr
+++ b/src/test/ui/nll/generator-upvar-mutability.stderr
@@ -1,6 +1,9 @@
-error[E0594]: cannot assign to immutable item `x`
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
   --> $DIR/generator-upvar-mutability.rs:18:9
    |
+LL |     let x = 0;
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     move || {
 LL |         x = 1;
    |         ^^^^^ cannot assign
 
diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr
index 3282fbba6c5..366bfc8fa20 100644
--- a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr
+++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `x` as mutable
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:63:24
    |
 LL | fn deref_mut_field1(x: Own<Point>) {
@@ -6,7 +6,7 @@ LL | fn deref_mut_field1(x: Own<Point>) {
 LL |     let __isize = &mut x.y; //~ ERROR cannot borrow
    |                        ^ cannot borrow as mutable
 
-error[E0596]: cannot borrow immutable item `*x` as mutable
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:75:10
    |
 LL | fn deref_extend_mut_field1(x: &Own<Point>) -> &mut isize {
@@ -14,7 +14,7 @@ LL | fn deref_extend_mut_field1(x: &Own<Point>) -> &mut isize {
 LL |     &mut x.y //~ ERROR cannot borrow
    |          ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `x` as mutable
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:98:5
    |
 LL | fn assign_field1<'a>(x: Own<Point>) {
@@ -22,7 +22,7 @@ LL | fn assign_field1<'a>(x: Own<Point>) {
 LL |     x.y = 3; //~ ERROR cannot borrow
    |     ^ cannot borrow as mutable
 
-error[E0596]: cannot borrow immutable item `*x` as mutable
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:102:5
    |
 LL | fn assign_field2<'a>(x: &'a Own<Point>) {
@@ -30,7 +30,7 @@ LL | fn assign_field2<'a>(x: &'a Own<Point>) {
 LL |     x.y = 3; //~ ERROR cannot borrow
    |     ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `x` as mutable
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:119:5
    |
 LL | fn deref_mut_method1(x: Own<Point>) {
@@ -38,7 +38,7 @@ LL | fn deref_mut_method1(x: Own<Point>) {
 LL |     x.set(0, 0); //~ ERROR cannot borrow
    |     ^ cannot borrow as mutable
 
-error[E0596]: cannot borrow immutable item `*x` as mutable
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:131:5
    |
 LL | fn deref_extend_mut_method1(x: &Own<Point>) -> &mut isize {
@@ -46,7 +46,7 @@ LL | fn deref_extend_mut_method1(x: &Own<Point>) -> &mut isize {
 LL |     x.y_mut() //~ ERROR cannot borrow
    |     ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `x` as mutable
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:139:6
    |
 LL | fn assign_method1<'a>(x: Own<Point>) {
@@ -54,7 +54,7 @@ LL | fn assign_method1<'a>(x: Own<Point>) {
 LL |     *x.y_mut() = 3; //~ ERROR cannot borrow
    |      ^ cannot borrow as mutable
 
-error[E0596]: cannot borrow immutable item `*x` as mutable
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:143:6
    |
 LL | fn assign_method2<'a>(x: &'a Own<Point>) {
diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr
index 0b1bfd8cee6..69bf246ff3f 100644
--- a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr
+++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `x` as mutable
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:39:25
    |
 LL | fn deref_mut1(x: Own<isize>) {
@@ -6,7 +6,7 @@ LL | fn deref_mut1(x: Own<isize>) {
 LL |     let __isize = &mut *x; //~ ERROR cannot borrow
    |                         ^ cannot borrow as mutable
 
-error[E0596]: cannot borrow immutable item `*x` as mutable
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:51:11
    |
 LL | fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize {
@@ -14,7 +14,7 @@ LL | fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize {
 LL |     &mut **x //~ ERROR cannot borrow
    |           ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `x` as mutable
+error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:59:6
    |
 LL | fn assign1<'a>(x: Own<isize>) {
@@ -22,7 +22,7 @@ LL | fn assign1<'a>(x: Own<isize>) {
 LL |     *x = 3; //~ ERROR cannot borrow
    |      ^ cannot borrow as mutable
 
-error[E0596]: cannot borrow immutable item `*x` as mutable
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:63:6
    |
 LL | fn assign2<'a>(x: &'a Own<isize>) {
diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
index c4bdef21de4..f752015c650 100644
--- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
+++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
@@ -12,7 +12,7 @@ LL | |         f((Box::new(|| {})))
 LL | |     }));
    | |_______- borrow later used here
 
-error[E0596]: cannot borrow immutable item `*f` as mutable
+error[E0596]: cannot borrow `*f` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:35:5
    |
 LL | fn test2<F>(f: &F) where F: FnMut() {
@@ -20,7 +20,7 @@ LL | fn test2<F>(f: &F) where F: FnMut() {
 LL |     (*f)();
    |     ^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `*f.f` as mutable
+error[E0596]: cannot borrow `*f.f` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:44:5
    |
 LL | fn test4(f: &Test) {
diff --git a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr
index 0bc614589e3..e9c0505af68 100644
--- a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr
+++ b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `*x` as mutable
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-call-method-from-mut-aliasable.rs:27:5
    |
 LL | fn b(x: &Foo) {
diff --git a/src/test/ui/span/borrowck-fn-in-const-b.nll.stderr b/src/test/ui/span/borrowck-fn-in-const-b.nll.stderr
index 1cb2c92833c..5e47d3271d4 100644
--- a/src/test/ui/span/borrowck-fn-in-const-b.nll.stderr
+++ b/src/test/ui/span/borrowck-fn-in-const-b.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `*x` as mutable
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-fn-in-const-b.rs:17:9
    |
 LL |     fn broken(x: &Vec<String>) {
diff --git a/src/test/ui/span/borrowck-object-mutability.nll.stderr b/src/test/ui/span/borrowck-object-mutability.nll.stderr
index b318e778f87..3f0eb97c7af 100644
--- a/src/test/ui/span/borrowck-object-mutability.nll.stderr
+++ b/src/test/ui/span/borrowck-object-mutability.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `*x` as mutable
+error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-object-mutability.rs:19:5
    |
 LL | fn borrowed_receiver(x: &Foo) {
@@ -7,7 +7,7 @@ LL |     x.borrowed();
 LL |     x.borrowed_mut(); //~ ERROR cannot borrow
    |     ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `*x` as mutable
+error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable
   --> $DIR/borrowck-object-mutability.rs:29:5
    |
 LL | fn owned_receiver(x: Box<Foo>) {
diff --git a/src/test/ui/span/mut-arg-hint.nll.stderr b/src/test/ui/span/mut-arg-hint.nll.stderr
index cd19059fdae..f264ea1f916 100644
--- a/src/test/ui/span/mut-arg-hint.nll.stderr
+++ b/src/test/ui/span/mut-arg-hint.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `*a` as mutable
+error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
   --> $DIR/mut-arg-hint.rs:13:9
    |
 LL |     fn foo(mut a: &String) {
@@ -6,7 +6,7 @@ LL |     fn foo(mut a: &String) {
 LL |         a.push_str("bar"); //~ ERROR cannot borrow immutable borrowed content
    |         ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `*a` as mutable
+error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
   --> $DIR/mut-arg-hint.rs:18:5
    |
 LL | pub fn foo<'a>(mut a: &'a String) {
@@ -14,7 +14,7 @@ LL | pub fn foo<'a>(mut a: &'a String) {
 LL |     a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content
    |     ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `*a` as mutable
+error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
   --> $DIR/mut-arg-hint.rs:25:9
    |
 LL |     pub fn foo(mut a: &String) {
diff --git a/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr b/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr
index 1a36b0c4839..215faf6c73c 100644
--- a/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr
+++ b/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow immutable item `**t` as mutable
+error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference
   --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:16:5
    |
 LL | fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
@@ -6,7 +6,7 @@ LL | fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: C
 LL |     *t //~ ERROR
    |     ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0596]: cannot borrow immutable item `**t` as mutable
+error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference
   --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:20:6
    |
 LL | fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {