]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #52242 - ashtneoi:suggest-ref-mut, r=pnkfelix
authorbors <bors@rust-lang.org>
Fri, 13 Jul 2018 17:08:39 +0000 (17:08 +0000)
committerbors <bors@rust-lang.org>
Fri, 13 Jul 2018 17:08:39 +0000 (17:08 +0000)
NLL: Suggest `ref mut` and `&mut self`

Fixes #51244. Supersedes #51249, I think.

Under the old lexical lifetimes, the compiler provided helpful suggestions about adding `mut` when you tried to mutate a variable bound as `&self` or (explicit) `ref`. NLL doesn't have those suggestions yet. This pull request adds them.

I didn't bother making the help text exactly the same as without NLL, but I can if that's important.

(Originally this was supposed to be part of #51612, but I got bogged down trying to fit everything in one PR.)

17 files changed:
src/librustc_borrowck/borrowck/mod.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/lib.rs
src/librustc_mir/util/mod.rs
src/test/ui/did_you_mean/issue-38147-1.nll.stderr
src/test/ui/did_you_mean/issue-39544.nll.stderr
src/test/ui/nll/issue-51244.rs [new file with mode: 0644]
src/test/ui/nll/issue-51244.stderr [new file with mode: 0644]
src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr
src/test/ui/rfc-2005-default-binding-mode/enum.stderr
src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr
src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr
src/test/ui/suggestions/issue-51244.nll.stderr [new file with mode: 0644]
src/test/ui/suggestions/issue-51244.rs [new file with mode: 0644]
src/test/ui/suggestions/issue-51244.stderr [new file with mode: 0644]
src/test/ui/suggestions/suggest-ref-mut.rs [new file with mode: 0644]
src/test/ui/suggestions/suggest-ref-mut.stderr [new file with mode: 0644]

index 7c2d5ba094ffa9e1d3a5ed7935860cb2fc7a7f35..79b4382369217bfb72776c41c6cfd5c72e55ff1c 100644 (file)
@@ -39,6 +39,7 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::query::Providers;
 use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin};
+use rustc_mir::util::suggest_ref_mut;
 use rustc::util::nodemap::FxHashSet;
 
 use std::cell::RefCell;
@@ -1206,15 +1207,15 @@ fn note_immutability_blame(&self,
                 self.note_immutable_local(db, error_node_id, node_id)
             }
             Some(ImmutabilityBlame::LocalDeref(node_id)) => {
-                let let_span = self.tcx.hir.span(node_id);
                 match self.local_binding_mode(node_id) {
                     ty::BindByReference(..) => {
-                        let snippet = self.tcx.sess.codemap().span_to_snippet(let_span);
-                        if let Ok(snippet) = snippet {
-                            db.span_label(
+                        let let_span = self.tcx.hir.span(node_id);
+                        let suggestion = suggest_ref_mut(self.tcx, let_span);
+                        if let Some((let_span, replace_str)) = suggestion {
+                            db.span_suggestion(
                                 let_span,
-                                format!("consider changing this to `{}`",
-                                         snippet.replace("ref ", "ref mut "))
+                                "use a mutable reference instead",
+                                replace_str,
                             );
                         }
                     }
index 9c5203f43d23e8863874693f9f4a0b639905b57d..03eaee362c70a7196f697ca1e0f6c971bc06faef 100644 (file)
@@ -44,6 +44,7 @@
 use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
 use util::borrowck_errors::{BorrowckErrors, Origin};
 use util::collect_writes::FindAssignments;
+use util::suggest_ref_mut;
 
 use self::borrow_set::{BorrowData, BorrowSet};
 use self::flows::Flows;
@@ -1837,17 +1838,41 @@ enum AccessKind {
             Place::Projection(box Projection {
                 base: Place::Local(local),
                 elem: ProjectionElem::Deref,
-            }) if self.mir.local_decls[*local].is_nonref_binding() =>
-            {
-                let (err_help_span, suggested_code) =
-                    find_place_to_suggest_ampmut(self.tcx, self.mir, *local);
-                err.span_suggestion(
-                    err_help_span,
-                    "consider changing this to be a mutable reference",
-                    suggested_code,
-                );
-
+            }) if self.mir.local_decls[*local].is_user_variable.is_some() => {
                 let local_decl = &self.mir.local_decls[*local];
+                let suggestion = match local_decl.is_user_variable.as_ref().unwrap() {
+                    ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf) => {
+                        Some(suggest_ampmut_self(local_decl))
+                    },
+
+                    ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
+                        binding_mode: ty::BindingMode::BindByValue(_),
+                        opt_ty_info,
+                        ..
+                    })) => Some(suggest_ampmut(
+                        self.tcx,
+                        self.mir,
+                        *local,
+                        local_decl,
+                        *opt_ty_info,
+                    )),
+
+                    ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
+                        binding_mode: ty::BindingMode::BindByReference(_),
+                        ..
+                    })) => suggest_ref_mut(self.tcx, local_decl.source_info.span),
+
+                    ClearCrossCrate::Clear => bug!("saw cleared local state"),
+                };
+
+                if let Some((err_help_span, suggested_code)) = suggestion {
+                    err.span_suggestion(
+                        err_help_span,
+                        "consider changing this to be a mutable reference",
+                        suggested_code,
+                    );
+                }
+
                 if let Some(name) = local_decl.name {
                     err.span_label(
                         span,
@@ -1874,13 +1899,16 @@ enum AccessKind {
         err.emit();
         return true;
 
-        // Returns the span to highlight and the associated text to
-        // present when suggesting that the user use an `&mut`.
-        //
+        fn suggest_ampmut_self<'cx, 'gcx, 'tcx>(
+            local_decl: &mir::LocalDecl<'tcx>,
+        ) -> (Span, String) {
+            (local_decl.source_info.span, "&mut self".to_string())
+        }
+
         // When we want to suggest a user change a local variable to be a `&mut`, there
         // are three potential "obvious" things to highlight:
         //
-        // let ident [: Type] [= RightHandSideExresssion];
+        // let ident [: Type] [= RightHandSideExpression];
         //     ^^^^^    ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^
         //     (1.)     (2.)              (3.)
         //
@@ -1889,48 +1917,44 @@ enum AccessKind {
         // for example, if the RHS is present and the Type is not, then the type is going to
         // be inferred *from* the RHS, which means we should highlight that (and suggest
         // that they borrow the RHS mutably).
-        fn find_place_to_suggest_ampmut<'cx, 'gcx, 'tcx>(
+        //
+        // This implementation attempts to emulate AST-borrowck prioritization
+        // by trying (3.), then (2.) and finally falling back on (1.).
+        fn suggest_ampmut<'cx, 'gcx, 'tcx>(
             tcx: TyCtxt<'cx, 'gcx, 'tcx>,
             mir: &Mir<'tcx>,
             local: Local,
+            local_decl: &mir::LocalDecl<'tcx>,
+            opt_ty_info: Option<Span>,
         ) -> (Span, String) {
-            // This implementation attempts to emulate AST-borrowck prioritization
-            // by trying (3.), then (2.) and finally falling back on (1.).
             let locations = mir.find_assignments(local);
             if locations.len() > 0 {
                 let assignment_rhs_span = mir.source_info(locations[0]).span;
                 let snippet = tcx.sess.codemap().span_to_snippet(assignment_rhs_span);
                 if let Ok(src) = snippet {
-                    // pnkfelix inherited code; believes intention is
-                    // highlighted text will always be `&<expr>` and
-                    // thus can transform to `&mut` by slicing off
-                    // first ASCII character and prepending "&mut ".
                     if src.starts_with('&') {
                         let borrowed_expr = src[1..].to_string();
-                        return (assignment_rhs_span, format!("&mut {}", borrowed_expr));
+                        return (
+                            assignment_rhs_span,
+                            format!("&mut {}", borrowed_expr),
+                        );
                     }
                 }
             }
 
-            let local_decl = &mir.local_decls[local];
-            let highlight_span = match local_decl.is_user_variable {
+            let highlight_span = match opt_ty_info {
                 // if this is a variable binding with an explicit type,
                 // try to highlight that for the suggestion.
-                Some(ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
-                    opt_ty_info: Some(ty_span),
-                    ..
-                }))) => ty_span,
-
-                Some(ClearCrossCrate::Clear) => bug!("saw cleared local state"),
+                Some(ty_span) => ty_span,
 
                 // otherwise, just highlight the span associated with
                 // the (MIR) LocalDecl.
-                _ => local_decl.source_info.span,
+                None => local_decl.source_info.span,
             };
 
             let ty_mut = local_decl.ty.builtin_deref(true).unwrap();
             assert_eq!(ty_mut.mutbl, hir::MutImmutable);
-            return (highlight_span, format!("&mut {}", ty_mut.ty));
+            (highlight_span, format!("&mut {}", ty_mut.ty))
         }
     }
 
index dc0d0b244633f28de71e578dbd136b23c9a3d5f5..92c0a2b475c20dacdeae77b02f1c6c2b505c49a9 100644 (file)
@@ -33,6 +33,7 @@
 #![feature(never_type)]
 #![feature(specialization)]
 #![feature(try_trait)]
+#![feature(unicode_internals)]
 
 #![recursion_limit="256"]
 
@@ -56,6 +57,7 @@
 extern crate log_settings;
 extern crate rustc_apfloat;
 extern crate byteorder;
+extern crate core;
 
 mod diagnostics;
 
index 19cd376688627de9d3fe4e79272f57b3656700e0..78e9dd23e83ae718387a9fa5bd1e47e2a50028e3 100644 (file)
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use core::unicode::property::Pattern_White_Space;
+use rustc::ty;
+use syntax_pos::Span;
+
 pub mod borrowck_errors;
 pub mod elaborate_drops;
 pub mod def_use;
 pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere};
 pub use self::graphviz::{write_mir_graphviz};
 pub use self::graphviz::write_node_label as write_graphviz_node_label;
+
+/// If possible, suggest replacing `ref` with `ref mut`.
+pub fn suggest_ref_mut<'cx, 'gcx, 'tcx>(
+    tcx: ty::TyCtxt<'cx, 'gcx, 'tcx>,
+    pattern_span: Span,
+) -> Option<(Span, String)> {
+    let hi_src = tcx.sess.codemap().span_to_snippet(pattern_span).unwrap();
+    if hi_src.starts_with("ref")
+        && hi_src["ref".len()..].starts_with(Pattern_White_Space)
+    {
+        let replacement = format!("ref mut{}", &hi_src["ref".len()..]);
+        Some((pattern_span, replacement))
+    } else {
+        None
+    }
+}
index 76b8c8ebf602940058e6828efbb1b1a2836de961..d156d64b9d693503dcdcce306e92bd9f047ae1da 100644 (file)
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow immutable item `*self.s` as mutable
   --> $DIR/issue-38147-1.rs:27:9
    |
 LL |     fn f(&self) {
-   |          ----- help: consider changing this to be a mutable reference: `&mut Foo<'_>`
+   |          ----- help: consider changing this to be a mutable reference: `&mut self`
 LL |         self.s.push('x'); //~ ERROR cannot borrow data mutably
    |         ^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
index 02c1debca69b24fa515978b7e4c757612eba2fc1..e2d2fcd63db122c244f273ec9dee1e991ea545c7 100644 (file)
@@ -10,7 +10,7 @@ error[E0596]: cannot borrow immutable item `self.x` as mutable
   --> $DIR/issue-39544.rs:26:17
    |
 LL |     fn foo<'z>(&'z self) {
-   |                -------- help: consider changing this to be a mutable reference: `&mut Z`
+   |                -------- help: consider changing this to be a mutable reference: `&mut self`
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
@@ -18,7 +18,7 @@ error[E0596]: cannot borrow immutable item `self.x` as mutable
   --> $DIR/issue-39544.rs:30:17
    |
 LL |     fn foo1(&self, other: &Z) {
-   |             ----- help: consider changing this to be a mutable reference: `&mut Z`
+   |             ----- help: consider changing this to be a mutable reference: `&mut self`
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
@@ -35,7 +35,7 @@ error[E0596]: cannot borrow immutable item `self.x` as mutable
   --> $DIR/issue-39544.rs:35:17
    |
 LL |     fn foo2<'a>(&'a self, other: &Z) {
-   |                 -------- help: consider changing this to be a mutable reference: `&mut Z`
+   |                 -------- help: consider changing this to be a mutable reference: `&mut self`
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
diff --git a/src/test/ui/nll/issue-51244.rs b/src/test/ui/nll/issue-51244.rs
new file mode 100644 (file)
index 0000000..f00ad3d
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+#![feature(nll)]
+
+fn main() {
+    let ref my_ref @ _ = 0;
+    *my_ref = 0;
+    //~^ ERROR cannot assign to `*my_ref` which is behind a `&` reference [E0594]
+}
diff --git a/src/test/ui/nll/issue-51244.stderr b/src/test/ui/nll/issue-51244.stderr
new file mode 100644 (file)
index 0000000..4e04aec
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to `*my_ref` which is behind a `&` reference
+  --> $DIR/issue-51244.rs:15:5
+   |
+LL |     let ref my_ref @ _ = 0;
+   |         -------------- help: consider changing this to be a mutable reference: `ref mut my_ref @ _`
+LL |     *my_ref = 0;
+   |     ^^^^^^^^^^^ `my_ref` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
index 8aa7e8a417c2bea3aeb5d778768278e29720e664..a9b2bca434cbac08a5409d17cc837dd4c7c323ae 100644 (file)
@@ -2,19 +2,19 @@ error[E0594]: cannot assign to `*x` which is behind a `&` reference
   --> $DIR/enum.rs:19:5
    |
 LL |     *x += 1; //~ ERROR cannot assign to immutable
-   |     ^^^^^^^ cannot assign
+   |     ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
 
 error[E0594]: cannot assign to `*x` which is behind a `&` reference
   --> $DIR/enum.rs:23:9
    |
 LL |         *x += 1; //~ ERROR cannot assign to immutable
-   |         ^^^^^^^ cannot assign
+   |         ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
 
 error[E0594]: cannot assign to `*x` which is behind a `&` reference
   --> $DIR/enum.rs:29:9
    |
 LL |         *x += 1; //~ ERROR cannot assign to immutable
-   |         ^^^^^^^ cannot assign
+   |         ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
 
 error: aborting due to 3 previous errors
 
index a7f3b507508e86d84def1936d79cb67fa5c8f9f8..ad05de9f3575f739e9b820c655f9f93b11a14a31 100644 (file)
@@ -1,24 +1,18 @@
 error[E0594]: cannot assign to immutable borrowed content `*x`
   --> $DIR/enum.rs:19:5
    |
-LL |     let Wrap(x) = &Wrap(3);
-   |              - consider changing this to `x`
 LL |     *x += 1; //~ ERROR cannot assign to immutable
    |     ^^^^^^^ cannot borrow as mutable
 
 error[E0594]: cannot assign to immutable borrowed content `*x`
   --> $DIR/enum.rs:23:9
    |
-LL |     if let Some(x) = &Some(3) {
-   |                 - consider changing this to `x`
 LL |         *x += 1; //~ ERROR cannot assign to immutable
    |         ^^^^^^^ cannot borrow as mutable
 
 error[E0594]: cannot assign to immutable borrowed content `*x`
   --> $DIR/enum.rs:29:9
    |
-LL |     while let Some(x) = &Some(3) {
-   |                    - consider changing this to `x`
 LL |         *x += 1; //~ ERROR cannot assign to immutable
    |         ^^^^^^^ cannot borrow as mutable
 
index 4e00dec761621ac58d317944e99a1275c270ea28..4c6149a8b7b30e8d93031a76839e67808bd07d62 100644 (file)
@@ -2,19 +2,19 @@ error[E0594]: cannot assign to `*n` which is behind a `&` reference
   --> $DIR/explicit-mut.rs:17:13
    |
 LL |             *n += 1; //~ ERROR cannot assign to immutable
-   |             ^^^^^^^ cannot assign
+   |             ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
 
 error[E0594]: cannot assign to `*n` which is behind a `&` reference
   --> $DIR/explicit-mut.rs:25:13
    |
 LL |             *n += 1; //~ ERROR cannot assign to immutable
-   |             ^^^^^^^ cannot assign
+   |             ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
 
 error[E0594]: cannot assign to `*n` which is behind a `&` reference
   --> $DIR/explicit-mut.rs:33:13
    |
 LL |             *n += 1; //~ ERROR cannot assign to immutable
-   |             ^^^^^^^ cannot assign
+   |             ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
 
 error: aborting due to 3 previous errors
 
index f2b9bde41ab3341274cdd319d871223829794907..8da67a6b5ee6520abd8084b16b04386959f4146b 100644 (file)
@@ -1,24 +1,18 @@
 error[E0594]: cannot assign to immutable borrowed content `*n`
   --> $DIR/explicit-mut.rs:17:13
    |
-LL |         Some(n) => {
-   |              - consider changing this to `n`
 LL |             *n += 1; //~ ERROR cannot assign to immutable
    |             ^^^^^^^ cannot borrow as mutable
 
 error[E0594]: cannot assign to immutable borrowed content `*n`
   --> $DIR/explicit-mut.rs:25:13
    |
-LL |         Some(n) => {
-   |              - consider changing this to `n`
 LL |             *n += 1; //~ ERROR cannot assign to immutable
    |             ^^^^^^^ cannot borrow as mutable
 
 error[E0594]: cannot assign to immutable borrowed content `*n`
   --> $DIR/explicit-mut.rs:33:13
    |
-LL |         Some(n) => {
-   |              - consider changing this to `n`
 LL |             *n += 1; //~ ERROR cannot assign to immutable
    |             ^^^^^^^ cannot borrow as mutable
 
diff --git a/src/test/ui/suggestions/issue-51244.nll.stderr b/src/test/ui/suggestions/issue-51244.nll.stderr
new file mode 100644 (file)
index 0000000..ce02ae2
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to `*my_ref` which is behind a `&` reference
+  --> $DIR/issue-51244.rs:13:5
+   |
+LL |     let ref my_ref @ _ = 0;
+   |         -------------- help: consider changing this to be a mutable reference: `ref mut my_ref @ _`
+LL |     *my_ref = 0; //~ ERROR cannot assign to immutable borrowed content `*my_ref` [E0594]
+   |     ^^^^^^^^^^^ `my_ref` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/suggestions/issue-51244.rs b/src/test/ui/suggestions/issue-51244.rs
new file mode 100644 (file)
index 0000000..50a2118
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+fn main() {
+    let ref my_ref @ _ = 0;
+    *my_ref = 0; //~ ERROR cannot assign to immutable borrowed content `*my_ref` [E0594]
+}
diff --git a/src/test/ui/suggestions/issue-51244.stderr b/src/test/ui/suggestions/issue-51244.stderr
new file mode 100644 (file)
index 0000000..997a742
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to immutable borrowed content `*my_ref`
+  --> $DIR/issue-51244.rs:13:5
+   |
+LL |     let ref my_ref @ _ = 0;
+   |         -------------- help: use a mutable reference instead: `ref mut my_ref @ _`
+LL |     *my_ref = 0; //~ ERROR cannot assign to immutable borrowed content `*my_ref` [E0594]
+   |     ^^^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/suggestions/suggest-ref-mut.rs b/src/test/ui/suggestions/suggest-ref-mut.rs
new file mode 100644 (file)
index 0000000..30b5371
--- /dev/null
@@ -0,0 +1,42 @@
+// 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.
+
+#![feature(nll)]
+
+struct X(usize);
+
+impl X {
+    fn zap(&self) {
+        //~^ HELP
+        //~| SUGGESTION &mut self
+        self.0 = 32;
+        //~^ ERROR
+    }
+}
+
+fn main() {
+    let ref foo = 16;
+    //~^ HELP
+    //~| SUGGESTION ref mut foo
+    *foo = 32;
+    //~^ ERROR
+    if let Some(ref bar) = Some(16) {
+        //~^ HELP
+        //~| SUGGESTION ref mut bar
+        *bar = 32;
+        //~^ ERROR
+    }
+    match 16 {
+        ref quo => { *quo = 32; },
+        //~^ ERROR
+        //~| HELP
+        //~| SUGGESTION ref mut quo
+    }
+}
diff --git a/src/test/ui/suggestions/suggest-ref-mut.stderr b/src/test/ui/suggestions/suggest-ref-mut.stderr
new file mode 100644 (file)
index 0000000..0b2b240
--- /dev/null
@@ -0,0 +1,38 @@
+error[E0594]: cannot assign to `self.0` which is behind a `&` reference
+  --> $DIR/suggest-ref-mut.rs:19:9
+   |
+LL |     fn zap(&self) {
+   |            ----- help: consider changing this to be a mutable reference: `&mut self`
+...
+LL |         self.0 = 32;
+   |         ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*foo` which is behind a `&` reference
+  --> $DIR/suggest-ref-mut.rs:28:5
+   |
+LL |     let ref foo = 16;
+   |         ------- help: consider changing this to be a mutable reference: `ref mut foo`
+...
+LL |     *foo = 32;
+   |     ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*bar` which is behind a `&` reference
+  --> $DIR/suggest-ref-mut.rs:33:9
+   |
+LL |     if let Some(ref bar) = Some(16) {
+   |                 ------- help: consider changing this to be a mutable reference: `ref mut bar`
+...
+LL |         *bar = 32;
+   |         ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*quo` which is behind a `&` reference
+  --> $DIR/suggest-ref-mut.rs:37:22
+   |
+LL |         ref quo => { *quo = 32; },
+   |         -------      ^^^^^^^^^ `quo` is a `&` reference, so the data it refers to cannot be written
+   |         |
+   |         help: consider changing this to be a mutable reference: `ref mut quo`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0594`.