]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #51639 - SimonSapin:missing-alloc, r=rkruppe
authorbors <bors@rust-lang.org>
Tue, 19 Jun 2018 23:37:09 +0000 (23:37 +0000)
committerbors <bors@rust-lang.org>
Tue, 19 Jun 2018 23:37:09 +0000 (23:37 +0000)
Update the error message for a missing global allocator

Don’t mention `#[default_lib_allocator]` (which is an implementation detail irrelevant to most users) and  instead suggest using `#[global_allocator]`, which is often the correct fix.

68 files changed:
src/liballoc/alloc.rs
src/liballoc/arc.rs
src/liballoc/raw_vec.rs
src/liballoc/rc.rs
src/libcore/alloc.rs
src/librustc/hir/map/mod.rs
src/librustc/mir/mod.rs
src/librustc/ty/binding.rs
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/build/block.rs
src/librustc_mir/build/expr/into.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/generator.rs
src/libstd/alloc.rs
src/libstd/collections/hash/table.rs
src/test/compile-fail/assign-imm-local-twice.rs
src/test/compile-fail/borrowck/borrowck-issue-14498.rs
src/test/compile-fail/borrowck/borrowck-overloaded-index-ref-index.rs
src/test/compile-fail/issue-45199.rs
src/test/compile-fail/liveness-assign-imm-local-in-loop.rs
src/test/compile-fail/liveness-assign-imm-local-in-op-eq.rs
src/test/compile-fail/liveness-assign-imm-local-with-drop.rs
src/test/compile-fail/liveness-assign-imm-local-with-init.rs
src/test/compile-fail/unboxed-closures-mutated-upvar-from-fn-closure.rs
src/test/run-pass/allocator-alloc-one.rs
src/test/run-pass/realloc-16687.rs
src/test/run-pass/regions-mock-codegen.rs
src/test/ui/asm-out-assign-imm.nll.stderr [new file with mode: 0644]
src/test/ui/augmented-assignments.nll.stderr
src/test/ui/borrowck/immutable-arg.stderr
src/test/ui/borrowck/issue-45983.nll.stderr
src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr
src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr
src/test/ui/command-line-diagnostics.nll.stderr
src/test/ui/did_you_mean/issue-31424.nll.stderr
src/test/ui/did_you_mean/issue-34126.nll.stderr
src/test/ui/did_you_mean/issue-34337.nll.stderr
src/test/ui/did_you_mean/issue-35937.nll.stderr
src/test/ui/did_you_mean/issue-37139.nll.stderr
src/test/ui/did_you_mean/issue-38147-1.nll.stderr
src/test/ui/did_you_mean/issue-38147-4.nll.stderr
src/test/ui/did_you_mean/issue-39544.nll.stderr
src/test/ui/did_you_mean/issue-40823.nll.stderr
src/test/ui/error-codes/E0389.nll.stderr
src/test/ui/issue-36400.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr
src/test/ui/lifetime-errors/liveness-assign-imm-local-notes.stderr
src/test/ui/macros/span-covering-argument-1.nll.stderr
src/test/ui/nll/issue-47388.stderr
src/test/ui/reassign-ref-mut.rs [new file with mode: 0644]
src/test/ui/reassign-ref-mut.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/explicit-mut.nll.stderr
src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr
src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr
src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr
src/test/ui/span/borrowck-fn-in-const-b.nll.stderr
src/test/ui/span/borrowck-object-mutability.nll.stderr
src/test/ui/span/mut-arg-hint.nll.stderr
src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr
src/test/ui/suggestions/fn-closure-mutable-capture.nll.stderr
src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr

index 04c8063ffebc5dbc613fab0bfc48f9d35b80c16a..84bd275df347c9c73b376c37e900ff3212be6900 100644 (file)
@@ -158,7 +158,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
         if !ptr.is_null() {
             ptr
         } else {
-            oom(layout)
+            handle_alloc_error(layout)
         }
     }
 }
@@ -184,13 +184,13 @@ pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
 ///
 /// The default behavior of this function is to print a message to standard error
 /// and abort the process.
-/// It can be replaced with [`set_oom_hook`] and [`take_oom_hook`].
+/// It can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`].
 ///
-/// [`set_oom_hook`]: ../../std/alloc/fn.set_oom_hook.html
-/// [`take_oom_hook`]: ../../std/alloc/fn.take_oom_hook.html
+/// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html
+/// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html
 #[stable(feature = "global_alloc", since = "1.28.0")]
 #[rustc_allocator_nounwind]
-pub fn oom(layout: Layout) -> ! {
+pub fn handle_alloc_error(layout: Layout) -> ! {
     #[allow(improper_ctypes)]
     extern "Rust" {
         #[lang = "oom"]
@@ -204,14 +204,14 @@ mod tests {
     extern crate test;
     use self::test::Bencher;
     use boxed::Box;
-    use alloc::{Global, Alloc, Layout, oom};
+    use alloc::{Global, Alloc, Layout, handle_alloc_error};
 
     #[test]
     fn allocate_zeroed() {
         unsafe {
             let layout = Layout::from_size_align(1024, 1).unwrap();
             let ptr = Global.alloc_zeroed(layout.clone())
-                .unwrap_or_else(|_| oom(layout));
+                .unwrap_or_else(|_| handle_alloc_error(layout));
 
             let mut i = ptr.cast::<u8>().as_ptr();
             let end = i.offset(layout.size() as isize);
index e3369f0a5b5bf52524b6e11d7e211ffdc4ac3f7c..0fbd1408f644f9e3f2da1e0e709ec8509d182738 100644 (file)
@@ -32,7 +32,7 @@
 use core::{isize, usize};
 use core::convert::From;
 
-use alloc::{Global, Alloc, Layout, box_free, oom};
+use alloc::{Global, Alloc, Layout, box_free, handle_alloc_error};
 use boxed::Box;
 use string::String;
 use vec::Vec;
@@ -554,7 +554,7 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
         let layout = Layout::for_value(&*fake_ptr);
 
         let mem = Global.alloc(layout)
-            .unwrap_or_else(|_| oom(layout));
+            .unwrap_or_else(|_| handle_alloc_error(layout));
 
         // Initialize the real ArcInner
         let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>;
index d1f140e96a3ae45c456a4a25211f289c17bc0f9b..2369ce648fda56ee64d5b92a097d9d7be7c25748 100644 (file)
@@ -14,7 +14,7 @@
 use core::ptr::{self, NonNull, Unique};
 use core::slice;
 
-use alloc::{Alloc, Layout, Global, oom};
+use alloc::{Alloc, Layout, Global, handle_alloc_error};
 use alloc::CollectionAllocErr;
 use alloc::CollectionAllocErr::*;
 use boxed::Box;
@@ -104,7 +104,7 @@ fn allocate_in(cap: usize, zeroed: bool, mut a: A) -> Self {
                 };
                 match result {
                     Ok(ptr) => ptr.cast(),
-                    Err(_) => oom(layout),
+                    Err(_) => handle_alloc_error(layout),
                 }
             };
 
@@ -319,7 +319,9 @@ pub fn double(&mut self) {
                                                  new_size);
                     match ptr_res {
                         Ok(ptr) => (new_cap, ptr.cast().into()),
-                        Err(_) => oom(Layout::from_size_align_unchecked(new_size, cur.align())),
+                        Err(_) => handle_alloc_error(
+                            Layout::from_size_align_unchecked(new_size, cur.align())
+                        ),
                     }
                 }
                 None => {
@@ -328,7 +330,7 @@ pub fn double(&mut self) {
                     let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
                     match self.a.alloc_array::<T>(new_cap) {
                         Ok(ptr) => (new_cap, ptr.into()),
-                        Err(_) => oom(Layout::array::<T>(new_cap).unwrap()),
+                        Err(_) => handle_alloc_error(Layout::array::<T>(new_cap).unwrap()),
                     }
                 }
             };
@@ -611,7 +613,9 @@ pub fn shrink_to_fit(&mut self, amount: usize) {
                                      old_layout,
                                      new_size) {
                     Ok(p) => self.ptr = p.cast().into(),
-                    Err(_) => oom(Layout::from_size_align_unchecked(new_size, align)),
+                    Err(_) => handle_alloc_error(
+                        Layout::from_size_align_unchecked(new_size, align)
+                    ),
                 }
             }
             self.cap = amount;
@@ -673,7 +677,7 @@ fn reserve_internal(
             };
 
             match (&res, fallibility) {
-                (Err(AllocErr), Infallible) => oom(new_layout),
+                (Err(AllocErr), Infallible) => handle_alloc_error(new_layout),
                 _ => {}
             }
 
index 84a6ecf710399d0f0fc923101da92599f7e567c4..32d624e8fbc7942f32660a2275a4ba8ec72ef43c 100644 (file)
 use core::ptr::{self, NonNull};
 use core::convert::From;
 
-use alloc::{Global, Alloc, Layout, box_free, oom};
+use alloc::{Global, Alloc, Layout, box_free, handle_alloc_error};
 use string::String;
 use vec::Vec;
 
@@ -662,7 +662,7 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
         let layout = Layout::for_value(&*fake_ptr);
 
         let mem = Global.alloc(layout)
-            .unwrap_or_else(|_| oom(layout));
+            .unwrap_or_else(|_| handle_alloc_error(layout));
 
         // Initialize the real RcBox
         let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox<T>;
index 353688d1b85583bd3b2f18e23049aee16872e062..0c074582281d6414617a30050bd82d5a20290160 100644 (file)
@@ -492,10 +492,10 @@ pub unsafe trait GlobalAlloc {
     /// library that aborts on memory exhaustion.)
     ///
     /// Clients wishing to abort computation in response to an
-    /// allocation error are encouraged to call the [`oom`] function,
+    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
     /// rather than directly invoking `panic!` or similar.
     ///
-    /// [`oom`]: ../../alloc/alloc/fn.oom.html
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
     #[stable(feature = "global_alloc", since = "1.28.0")]
     unsafe fn alloc(&self, layout: Layout) -> *mut u8;
 
@@ -529,10 +529,10 @@ pub unsafe trait GlobalAlloc {
     /// just as in `alloc`.
     ///
     /// Clients wishing to abort computation in response to an
-    /// allocation error are encouraged to call the [`oom`] function,
+    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
     /// rather than directly invoking `panic!` or similar.
     ///
-    /// [`oom`]: ../../alloc/alloc/fn.oom.html
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
     #[stable(feature = "global_alloc", since = "1.28.0")]
     unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
         let size = layout.size();
@@ -589,10 +589,10 @@ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
     /// library that aborts on memory exhaustion.)
     ///
     /// Clients wishing to abort computation in response to a
-    /// reallocation error are encouraged to call the [`oom`] function,
+    /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
     /// rather than directly invoking `panic!` or similar.
     ///
-    /// [`oom`]: ../../alloc/alloc/fn.oom.html
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
     #[stable(feature = "global_alloc", since = "1.28.0")]
     unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
         let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
@@ -733,10 +733,10 @@ pub unsafe trait Alloc {
     /// library that aborts on memory exhaustion.)
     ///
     /// Clients wishing to abort computation in response to an
-    /// allocation error are encouraged to call the [`oom`] function,
+    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
     /// rather than directly invoking `panic!` or similar.
     ///
-    /// [`oom`]: ../../alloc/alloc/fn.oom.html
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
     unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr>;
 
     /// Deallocate the memory referenced by `ptr`.
@@ -843,10 +843,10 @@ fn usable_size(&self, layout: &Layout) -> (usize, usize) {
     /// library that aborts on memory exhaustion.)
     ///
     /// Clients wishing to abort computation in response to a
-    /// reallocation error are encouraged to call the [`oom`] function,
+    /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
     /// rather than directly invoking `panic!` or similar.
     ///
-    /// [`oom`]: ../../alloc/alloc/fn.oom.html
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
     unsafe fn realloc(&mut self,
                       ptr: NonNull<u8>,
                       layout: Layout,
@@ -889,10 +889,10 @@ unsafe fn realloc(&mut self,
     /// constraints, just as in `alloc`.
     ///
     /// Clients wishing to abort computation in response to an
-    /// allocation error are encouraged to call the [`oom`] function,
+    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
     /// rather than directly invoking `panic!` or similar.
     ///
-    /// [`oom`]: ../../alloc/alloc/fn.oom.html
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
     unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
         let size = layout.size();
         let p = self.alloc(layout);
@@ -917,10 +917,10 @@ unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocEr
     /// constraints, just as in `alloc`.
     ///
     /// Clients wishing to abort computation in response to an
-    /// allocation error are encouraged to call the [`oom`] function,
+    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
     /// rather than directly invoking `panic!` or similar.
     ///
-    /// [`oom`]: ../../alloc/alloc/fn.oom.html
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
     unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr> {
         let usable_size = self.usable_size(&layout);
         self.alloc(layout).map(|p| Excess(p, usable_size.1))
@@ -941,10 +941,10 @@ unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr> {
     /// constraints, just as in `realloc`.
     ///
     /// Clients wishing to abort computation in response to a
-    /// reallocation error are encouraged to call the [`oom`] function,
+    /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
     /// rather than directly invoking `panic!` or similar.
     ///
-    /// [`oom`]: ../../alloc/alloc/fn.oom.html
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
     unsafe fn realloc_excess(&mut self,
                              ptr: NonNull<u8>,
                              layout: Layout,
@@ -986,7 +986,7 @@ unsafe fn realloc_excess(&mut self,
     /// unable to assert that the memory block referenced by `ptr`
     /// could fit `layout`.
     ///
-    /// Note that one cannot pass `CannotReallocInPlace` to the `oom`
+    /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error`
     /// function; clients are expected either to be able to recover from
     /// `grow_in_place` failures without aborting, or to fall back on
     /// another reallocation method before resorting to an abort.
@@ -1041,7 +1041,7 @@ unsafe fn grow_in_place(&mut self,
     /// unable to assert that the memory block referenced by `ptr`
     /// could fit `layout`.
     ///
-    /// Note that one cannot pass `CannotReallocInPlace` to the `oom`
+    /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error`
     /// function; clients are expected either to be able to recover from
     /// `shrink_in_place` failures without aborting, or to fall back
     /// on another reallocation method before resorting to an abort.
@@ -1090,10 +1090,10 @@ unsafe fn shrink_in_place(&mut self,
     /// will *not* yield undefined behavior.
     ///
     /// Clients wishing to abort computation in response to an
-    /// allocation error are encouraged to call the [`oom`] function,
+    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
     /// rather than directly invoking `panic!` or similar.
     ///
-    /// [`oom`]: ../../alloc/alloc/fn.oom.html
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
     fn alloc_one<T>(&mut self) -> Result<NonNull<T>, AllocErr>
         where Self: Sized
     {
@@ -1159,10 +1159,10 @@ unsafe fn dealloc_one<T>(&mut self, ptr: NonNull<T>)
     /// Always returns `Err` on arithmetic overflow.
     ///
     /// Clients wishing to abort computation in response to an
-    /// allocation error are encouraged to call the [`oom`] function,
+    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
     /// rather than directly invoking `panic!` or similar.
     ///
-    /// [`oom`]: ../../alloc/alloc/fn.oom.html
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
     fn alloc_array<T>(&mut self, n: usize) -> Result<NonNull<T>, AllocErr>
         where Self: Sized
     {
@@ -1206,10 +1206,10 @@ fn alloc_array<T>(&mut self, n: usize) -> Result<NonNull<T>, AllocErr>
     /// Always returns `Err` on arithmetic overflow.
     ///
     /// Clients wishing to abort computation in response to a
-    /// reallocation error are encouraged to call the [`oom`] function,
+    /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
     /// rather than directly invoking `panic!` or similar.
     ///
-    /// [`oom`]: ../../alloc/alloc/fn.oom.html
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
     unsafe fn realloc_array<T>(&mut self,
                                ptr: NonNull<T>,
                                n_old: usize,
index 9df55e52061634962c67b5e5dcd338cf497f1fea..d2e04ef31c86afffe55638868b4cbd52ea1824c6 100644 (file)
@@ -170,6 +170,40 @@ fn to_node(self) -> Option<Node<'hir>> {
         })
     }
 
+    fn fn_decl(&self) -> Option<&FnDecl> {
+        match self {
+            EntryItem(_, _, ref item) => {
+                match item.node {
+                    ItemFn(ref fn_decl, _, _, _, _, _) => Some(&fn_decl),
+                    _ => None,
+                }
+            }
+
+            EntryTraitItem(_, _, ref item) => {
+                match item.node {
+                    TraitItemKind::Method(ref method_sig, _) => Some(&method_sig.decl),
+                    _ => None
+                }
+            }
+
+            EntryImplItem(_, _, ref item) => {
+                match item.node {
+                    ImplItemKind::Method(ref method_sig, _) => Some(&method_sig.decl),
+                    _ => None,
+                }
+            }
+
+            EntryExpr(_, _, ref expr) => {
+                match expr.node {
+                    ExprClosure(_, ref fn_decl, ..) => Some(&fn_decl),
+                    _ => None,
+                }
+            }
+
+            _ => None
+        }
+    }
+
     fn associated_body(self) -> Option<BodyId> {
         match self {
             EntryItem(_, _, item) => {
@@ -502,6 +536,14 @@ pub fn body(&self, id: BodyId) -> &'hir Body {
         self.forest.krate.body(id)
     }
 
+    pub fn fn_decl(&self, node_id: ast::NodeId) -> Option<FnDecl> {
+        if let Some(entry) = self.find_entry(node_id) {
+            entry.fn_decl().map(|fd| fd.clone())
+        } else {
+            bug!("no entry for node_id `{}`", node_id)
+        }
+    }
+
     /// Returns the `NodeId` that corresponds to the definition of
     /// which this is the body of, i.e. a `fn`, `const` or `static`
     /// item (possibly associated), a closure, or a `hir::AnonConst`.
index b2ff36cb87c78f8876a6613c5e5038ecaa39b777..20a0df2a1717780c9c447f8cafead3cbb4dea256 100644 (file)
@@ -228,7 +228,7 @@ pub fn local_kind(&self, local: Local) -> LocalKind {
     pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
         (self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
             let local = Local::new(index);
-            if self.local_decls[local].is_user_variable {
+            if self.local_decls[local].is_user_variable.is_some() {
                 None
             } else {
                 Some(local)
@@ -241,7 +241,7 @@ pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
     pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
         (self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
             let local = Local::new(index);
-            if self.local_decls[local].is_user_variable {
+            if self.local_decls[local].is_user_variable.is_some() {
                 Some(local)
             } else {
                 None
@@ -255,7 +255,7 @@ pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
         (1..self.local_decls.len()).filter_map(move |index| {
             let local = Local::new(index);
             let decl = &self.local_decls[local];
-            if (decl.is_user_variable || index < self.arg_count + 1)
+            if (decl.is_user_variable.is_some() || index < self.arg_count + 1)
                && decl.mutability == Mutability::Mut
             {
                 Some(local)
@@ -351,7 +351,7 @@ fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
     }
 }
 
-#[derive(Clone, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum ClearCrossCrate<T> {
     Clear,
     Set(T)
@@ -382,6 +382,16 @@ pub enum Mutability {
     Not,
 }
 
+impl From<Mutability> for hir::Mutability {
+    fn from(m: Mutability) -> Self {
+        match m {
+            Mutability::Mut => hir::MutMutable,
+            Mutability::Not => hir::MutImmutable,
+        }
+    }
+}
+
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
 pub enum BorrowKind {
     /// Data must be immutable and is aliasable.
@@ -463,6 +473,33 @@ pub enum LocalKind {
     ReturnPointer,
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+pub struct VarBindingForm {
+    /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`?
+    pub binding_mode: ty::BindingMode,
+    /// If an explicit type was provided for this variable binding,
+    /// this holds the source Span of that type.
+    ///
+    /// NOTE: If you want to change this to a `HirId`, be wary that
+    /// doing so breaks incremental compilation (as of this writing),
+    /// while a `Span` does not cause our tests to fail.
+    pub opt_ty_info: Option<Span>,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+pub enum BindingForm {
+    /// This is a binding for a non-`self` binding, or a `self` that has an explicit type.
+    Var(VarBindingForm),
+    /// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit.
+    ImplicitSelf,
+}
+
+CloneTypeFoldableAndLiftImpls! { BindingForm, }
+
+impl_stable_hash_for!(struct self::VarBindingForm { binding_mode, opt_ty_info });
+
+impl_stable_hash_for!(enum self::BindingForm { Var(binding), ImplicitSelf, });
+
 /// A MIR local.
 ///
 /// This can be a binding declared by the user, a temporary inserted by the compiler, a function
@@ -474,8 +511,14 @@ pub struct LocalDecl<'tcx> {
     /// Temporaries and the return place are always mutable.
     pub mutability: Mutability,
 
-    /// True if this corresponds to a user-declared local variable.
-    pub is_user_variable: bool,
+    /// Some(binding_mode) if this corresponds to a user-declared local variable.
+    ///
+    /// This is solely used for local diagnostics when generating
+    /// warnings/errors when compiling the current crate, and
+    /// therefore it need not be visible across crates. pnkfelix
+    /// currently hypothesized we *need* to wrap this in a
+    /// `ClearCrossCrate` as long as it carries as `HirId`.
+    pub is_user_variable: Option<ClearCrossCrate<BindingForm>>,
 
     /// True if this is an internal local
     ///
@@ -592,6 +635,45 @@ pub struct LocalDecl<'tcx> {
 }
 
 impl<'tcx> LocalDecl<'tcx> {
+    /// Returns true only if local is a binding that can itself be
+    /// made mutable via the addition of the `mut` keyword, namely
+    /// something like the occurrences of `x` in:
+    /// - `fn foo(x: Type) { ... }`,
+    /// - `let x = ...`,
+    /// - or `match ... { C(x) => ... }`
+    pub fn can_be_made_mutable(&self) -> bool
+    {
+        match self.is_user_variable {
+            Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+                binding_mode: ty::BindingMode::BindByValue(_),
+                opt_ty_info: _,
+            }))) => true,
+
+            // FIXME: might be able to thread the distinction between
+            // `self`/`mut self`/`&self`/`&mut self` into the
+            // `BindingForm::ImplicitSelf` variant, (and then return
+            // true here for solely the first case).
+            _ => false,
+        }
+    }
+
+    /// Returns true if local is definitely not a `ref ident` or
+    /// `ref mut ident` binding. (Such bindings cannot be made into
+    /// mutable bindings, but the inverse does not necessarily hold).
+    pub fn is_nonref_binding(&self) -> bool
+    {
+        match self.is_user_variable {
+            Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+                binding_mode: ty::BindingMode::BindByValue(_),
+                opt_ty_info: _,
+            }))) => true,
+
+            Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf)) => true,
+
+            _ => false,
+        }
+    }
+
     /// Create a new `LocalDecl` for a temporary.
     #[inline]
     pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self {
@@ -605,7 +687,7 @@ pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self {
             },
             visibility_scope: OUTERMOST_SOURCE_SCOPE,
             internal: false,
-            is_user_variable: false
+            is_user_variable: None,
         }
     }
 
@@ -622,7 +704,7 @@ pub fn new_internal(ty: Ty<'tcx>, span: Span) -> Self {
             },
             visibility_scope: OUTERMOST_SOURCE_SCOPE,
             internal: true,
-            is_user_variable: false
+            is_user_variable: None,
         }
     }
 
@@ -641,7 +723,7 @@ pub fn new_return_place(return_ty: Ty, span: Span) -> LocalDecl {
             visibility_scope: OUTERMOST_SOURCE_SCOPE,
             internal: false,
             name: None,     // FIXME maybe we do want some name here?
-            is_user_variable: false
+            is_user_variable: None,
         }
     }
 }
index 3db61b76cc55c57e3a7f8ce54672bbe7f75f05ec..971b3c3d14aebe3b88ed5ad042b34c5e4e92c23b 100644 (file)
@@ -18,6 +18,8 @@ pub enum BindingMode {
     BindByValue(Mutability),
 }
 
+CloneTypeFoldableAndLiftImpls! { BindingMode, }
+
 impl BindingMode {
     pub fn convert(ba: BindingAnnotation) -> BindingMode {
         match ba {
index 9061af1b68ca4717c9f4c562d22da3b79fb45013..38d1ac2cb4ad0482b97c5ae4a29fce422c9d5129 100644 (file)
@@ -593,11 +593,18 @@ pub(super) fn report_illegal_mutation_of_borrowed(
         err.emit();
     }
 
+    /// Reports an illegal reassignment; for example, an assignment to
+    /// (part of) a non-`mut` local that occurs potentially after that
+    /// local has already been initialized. `place` is the path being
+    /// assigned; `err_place` is a place providing a reason why
+    /// `place` is not mutable (e.g. the non-`mut` local `x` in an
+    /// assignment to `x.f`).
     pub(super) fn report_illegal_reassignment(
         &mut self,
         _context: Context,
         (place, span): (&Place<'tcx>, Span),
         assigned_span: Span,
+        err_place: &Place<'tcx>,
     ) {
         let is_arg = if let Place::Local(local) = place {
             if let LocalKind::Arg = self.mir.local_kind(*local) {
@@ -621,9 +628,7 @@ pub(super) fn report_illegal_reassignment(
             "cannot assign twice to immutable variable"
         };
         if span != assigned_span {
-            if is_arg {
-                err.span_label(assigned_span, "argument not declared as `mut`");
-            } else {
+            if !is_arg {
                 let value_msg = match self.describe_place(place) {
                     Some(name) => format!("`{}`", name),
                     None => "value".to_owned(),
@@ -631,6 +636,15 @@ pub(super) fn report_illegal_reassignment(
                 err.span_label(assigned_span, format!("first assignment to {}", value_msg));
             }
         }
+        if let Place::Local(local) = err_place {
+            let local_decl = &self.mir.local_decls[*local];
+            if let Some(name) = local_decl.name {
+                if local_decl.can_be_made_mutable() {
+                    err.span_label(local_decl.source_info.span,
+                                   format!("consider changing this to `mut {}`", name));
+                }
+            }
+        }
         err.span_label(span, msg);
         err.emit();
     }
index c43ea0360ee1394101d923fbe5d9aab4b42eba44..122b2df4766adbce7da67fc54a300f40e4049f52 100644 (file)
@@ -18,7 +18,7 @@
 use rustc::ty::{self, ParamEnv, TyCtxt};
 use rustc::ty::query::Providers;
 use rustc::lint::builtin::UNUSED_MUT;
-use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
+use rustc::mir::{self, AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
 use rustc::mir::{ClearCrossCrate, Local, Location, Place, Mir, Mutability, Operand};
 use rustc::mir::{Projection, ProjectionElem, Rvalue, Field, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
@@ -278,7 +278,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     // to the set.
     let temporary_used_locals: FxHashSet<Local> =
         mbcx.used_mut.iter()
-            .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable)
+            .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some())
             .cloned()
             .collect();
 
@@ -1398,9 +1398,10 @@ fn check_if_reassignment_to_immutable_state(
     ) {
         debug!("check_if_reassignment_to_immutable_state({:?})", place);
         // determine if this path has a non-mut owner (and thus needs checking).
-        if let Ok(..) = self.is_mutable(place, LocalMutationIsAllowed::No) {
-            return;
-        }
+        let err_place = match self.is_mutable(place, LocalMutationIsAllowed::No) {
+            Ok(..) => return,
+            Err(place) => place,
+        };
         debug!(
             "check_if_reassignment_to_immutable_state({:?}) - is an imm local",
             place
@@ -1410,7 +1411,7 @@ fn check_if_reassignment_to_immutable_state(
             let init = self.move_data.inits[i];
             let init_place = &self.move_data.move_paths[init.path].place;
             if places_conflict(self.tcx, self.mir, &init_place, place, Deep) {
-                self.report_illegal_reassignment(context, (place, span), init.span);
+                self.report_illegal_reassignment(context, (place, span), init.span, err_place);
                 break;
             }
         }
@@ -1658,36 +1659,6 @@ fn check_if_assigned_path_is_moved(
         }
     }
 
-    fn specialized_description(&self, place:&Place<'tcx>) -> Option<String>{
-        if let Some(_name) = self.describe_place(place) {
-            Some(format!("data in a `&` reference"))
-        } else {
-            None
-        }
-    }
-
-    fn get_default_err_msg(&self, place:&Place<'tcx>) -> String{
-        match self.describe_place(place) {
-            Some(name) => format!("immutable item `{}`", name),
-            None => "immutable item".to_owned(),
-        }
-    }
-
-    fn get_secondary_err_msg(&self, place:&Place<'tcx>) -> String{
-        match self.specialized_description(place) {
-            Some(_) => format!("data in a `&` reference"),
-            None => self.get_default_err_msg(place)
-        }
-    }
-
-    fn get_primary_err_msg(&self, place:&Place<'tcx>) -> String{
-        if let Some(name) = self.describe_place(place) {
-            format!("`{}` is a `&` reference, so the data it refers to cannot be written", name)
-        } else {
-            format!("cannot assign through `&`-reference")
-        }
-    }
-
     /// Check the permissions for the given place and read or write kind
     ///
     /// Returns true if an error is reported, false otherwise.
@@ -1702,7 +1673,15 @@ fn check_access_permissions(
             "check_access_permissions({:?}, {:?}, {:?})",
             place, kind, is_local_mutation_allowed
         );
-        let mut error_reported = false;
+
+        #[derive(Copy, Clone, Debug)]
+        enum AccessKind {
+            MutableBorrow,
+            Mutate,
+        }
+        let error_access;
+        let the_place_err;
+
         match kind {
             Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Unique))
             | Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. }))
@@ -1715,91 +1694,29 @@ fn check_access_permissions(
                     BorrowKind::Shared => unreachable!(),
                 };
                 match self.is_mutable(place, is_local_mutation_allowed) {
-                    Ok(root_place) => self.add_used_mut(root_place, flow_state),
+                    Ok(root_place) => {
+                        self.add_used_mut(root_place, flow_state);
+                        return false;
+                    }
                     Err(place_err) => {
-                        error_reported = true;
-                        let item_msg = self.get_default_err_msg(place);
-                        let mut err = self.tcx
-                            .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir);
-                        err.span_label(span, "cannot borrow as mutable");
-
-                        if place != place_err {
-                            if let Some(name) = self.describe_place(place_err) {
-                                err.note(&format!("the value which is causing this path not to be \
-                                    mutable is...: `{}`", name));
-                            }
-                        }
-
-                        err.emit();
+                        error_access = AccessKind::MutableBorrow;
+                        the_place_err = place_err;
                     }
                 }
             }
             Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => {
                 match self.is_mutable(place, is_local_mutation_allowed) {
-                    Ok(root_place) => self.add_used_mut(root_place, flow_state),
+                    Ok(root_place) => {
+                        self.add_used_mut(root_place, flow_state);
+                        return false;
+                    }
                     Err(place_err) => {
-                        error_reported = true;
-
-                        let err_info = if let Place::Projection(
-                            box Projection {
-                                base: Place::Local(local),
-                                elem: ProjectionElem::Deref
-                            }
-                        ) = *place_err {
-                            let locations = self.mir.find_assignments(local);
-                            if locations.len() > 0 {
-                                let item_msg = if error_reported {
-                                    self.get_secondary_err_msg(&Place::Local(local))
-                                } else {
-                                    self.get_default_err_msg(place)
-                                };
-                                let sp = self.mir.source_info(locations[0]).span;
-                                let mut to_suggest_span = String::new();
-                                if let Ok(src) =
-                                    self.tcx.sess.codemap().span_to_snippet(sp) {
-                                        to_suggest_span = src[1..].to_string();
-                                };
-                                Some((sp,
-                                      "consider changing this to be a \
-                                      mutable reference",
-                                      to_suggest_span,
-                                      item_msg,
-                                      self.get_primary_err_msg(&Place::Local(local))))
-                            } else {
-                                None
-                            }
-                        } else {
-                            None
-                        };
-
-                        if let Some((err_help_span,
-                                     err_help_stmt,
-                                     to_suggest_span,
-                                     item_msg,
-                                     sec_span)) = err_info {
-                            let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
-                            err.span_suggestion(err_help_span,
-                                                err_help_stmt,
-                                                format!("&mut {}", to_suggest_span));
-                            if place != place_err {
-                                err.span_label(span, sec_span);
-                            }
-                            err.emit()
-                        } else {
-                            let item_msg = self.get_default_err_msg(place);
-                            let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
-                            err.span_label(span, "cannot mutate");
-                            if place != place_err {
-                                if let Some(name) = self.describe_place(place_err) {
-                                    err.note(&format!("the value which is causing this path not \
-                                                       to be mutable is...: `{}`", name));
-                                }
-                            }
-                            err.emit();
-                        }
+                        error_access = AccessKind::Mutate;
+                        the_place_err = place_err;
                     }
                 }
             }
+
             Reservation(WriteKind::Move)
             | Write(WriteKind::Move)
             | Reservation(WriteKind::StorageDeadOrDrop)
@@ -1815,15 +1732,174 @@ fn check_access_permissions(
                         ),
                     );
                 }
+                return false;
+            }
+            Activation(..) => {
+                // permission checks are done at Reservation point.
+                return false;
             }
-            Activation(..) => {} // permission checks are done at Reservation point.
             Read(ReadKind::Borrow(BorrowKind::Unique))
             | Read(ReadKind::Borrow(BorrowKind::Mut { .. }))
             | Read(ReadKind::Borrow(BorrowKind::Shared))
-            | Read(ReadKind::Copy) => {} // Access authorized
+            | Read(ReadKind::Copy) => {
+                // Access authorized
+                return false;
+            }
         }
 
-        error_reported
+        // at this point, we have set up the error reporting state.
+
+        let mut err;
+        let item_msg = match self.describe_place(place) {
+            Some(name) => format!("immutable item `{}`", name),
+            None => "immutable item".to_owned(),
+        };
+
+        // `act` and `acted_on` are strings that let us abstract over
+        // the verbs used in some diagnostic messages.
+        let act; let acted_on;
+
+        match error_access {
+            AccessKind::Mutate => {
+                let item_msg = match the_place_err {
+                    Place::Projection(box Projection {
+                        base: _,
+                        elem: ProjectionElem::Deref }
+                    ) => match self.describe_place(place) {
+                        Some(description) =>
+                            format!("`{}` which is behind a `&` reference", description),
+                        None => format!("data in a `&` reference"),
+                    },
+                    _ => item_msg,
+                };
+                err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
+                act = "assign"; acted_on = "written";
+            }
+            AccessKind::MutableBorrow => {
+                err = self.tcx
+                    .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir);
+                act = "borrow as mutable"; acted_on = "borrowed as mutable";
+            }
+        }
+
+        match the_place_err {
+            // We want to suggest users use `let mut` for local (user
+            // variable) mutations...
+            Place::Local(local) if self.mir.local_decls[*local].can_be_made_mutable() => {
+                // ... but it doesn't make sense to suggest it on
+                // variables that are `ref x`, `ref mut x`, `&self`,
+                // or `&mut self` (such variables are simply not
+                // mutable)..
+                let local_decl = &self.mir.local_decls[*local];
+                assert_eq!(local_decl.mutability, Mutability::Not);
+
+                err.span_label(span, format!("cannot {ACT}", ACT=act));
+                err.span_suggestion(local_decl.source_info.span,
+                                    "consider changing this to be mutable",
+                                    format!("mut {}", local_decl.name.unwrap()));
+            }
+
+            // complete hack to approximate old AST-borrowck
+            // diagnostic: if the span starts with a mutable borrow of
+            // a local variable, then just suggest the user remove it.
+            Place::Local(_) if {
+                if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
+                    snippet.starts_with("&mut ")
+                } else {
+                    false
+                }
+            } => {
+                err.span_label(span, format!("cannot {ACT}", ACT=act));
+                err.span_label(span, "try removing `&mut` here");
+            }
+
+            // We want to point out when a `&` can be readily replaced
+            // with an `&mut`.
+            //
+            // FIXME: can this case be generalized to work for an
+            // arbitrary base for the projection?
+            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);
+
+                let local_decl = &self.mir.local_decls[*local];
+                if let Some(name) = local_decl.name {
+                    err.span_label(
+                        span, format!("`{NAME}` is a `&` reference, \
+                                       so the data it refers to cannot be {ACTED_ON}",
+                                      NAME=name, ACTED_ON=acted_on));
+                } else {
+                    err.span_label(span, format!("cannot {ACT} through `&`-reference", ACT=act));
+                }
+            }
+
+            _ => {
+                err.span_label(span, format!("cannot {ACT}", ACT=act));
+            }
+        }
+
+        err.emit();
+        return true;
+
+        // Returns the span to highlight and the associated text to
+        // present when suggesting that the user use an `&mut`.
+        //
+        // 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];
+        //     ^^^^^    ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^
+        //     (1.)     (2.)              (3.)
+        //
+        // We can always fallback on highlighting the first. But chances are good that
+        // the user experience will be better if we highlight one of the others if possible;
+        // 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>(tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+                                                         mir: &Mir<'tcx>,
+                                                         local: Local) -> (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 ".
+                    let borrowed_expr = src[1..].to_string();
+                    return (assignment_rhs_span, format!("&mut {}", borrowed_expr));
+                }
+            }
+
+            let local_decl = &mir.local_decls[local];
+            let highlight_span = match local_decl.is_user_variable {
+                // 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"),
+
+                // otherwise, just highlight the span associated with
+                // the (MIR) LocalDecl.
+                _ => 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));
+        }
     }
 
     /// Adds the place into the used mutable variables set
index 7096f91dc1ddb0751402e9f72f7588a08bf7fb3c..0fd55f752b84f38869e97b2e9da370ce62111226 100644 (file)
@@ -137,7 +137,7 @@ fn ast_block_stmts(&mut self,
                             }
                         }
 
-                        this.visit_bindings(&pattern, &mut |this, _, _, node, span, _| {
+                        this.visit_bindings(&pattern, &mut |this, _, _, _, node, span, _| {
                             this.storage_live_binding(block, node, span, OutsideGuard);
                             this.schedule_drop_for_binding(node, span, OutsideGuard);
                         })
index fbd771fbe500d7eb8fab1b18401ad1873a271d2a..94b387abe3c13e7d06ed13f103acc0ef1bda7c35 100644 (file)
@@ -249,7 +249,7 @@ pub fn into_expr(&mut self,
                         source_info,
                         visibility_scope: source_info.scope,
                         internal: true,
-                        is_user_variable: false
+                        is_user_variable: None,
                     });
                     let ptr_temp = Place::Local(ptr_temp);
                     let block = unpack!(this.into(&ptr_temp, block, ptr));
index 062a48a8c434d02e5029eedadb1cb1705ab884af..b6af0ed2a4a1c448ebdf65d964a2ecc9fd3b80a9 100644 (file)
@@ -307,7 +307,7 @@ pub fn declare_bindings(&mut self,
         assert!(!(visibility_scope.is_some() && lint_level.is_explicit()),
                 "can't have both a visibility and a lint scope at the same time");
         let mut scope = self.source_scope;
-        self.visit_bindings(pattern, &mut |this, mutability, name, var, span, ty| {
+        self.visit_bindings(pattern, &mut |this, mutability, name, mode, var, span, ty| {
             if visibility_scope.is_none() {
                 visibility_scope = Some(this.new_source_scope(scope_span,
                                                            LintLevel::Inherited,
@@ -325,7 +325,7 @@ pub fn declare_bindings(&mut self,
                 scope,
             };
             let visibility_scope = visibility_scope.unwrap();
-            this.declare_binding(source_info, visibility_scope, mutability, name, var,
+            this.declare_binding(source_info, visibility_scope, mutability, name, mode, var,
                                  ty, has_guard);
         });
         visibility_scope
@@ -359,11 +359,11 @@ pub fn schedule_drop_for_binding(&mut self,
     }
 
     pub fn visit_bindings<F>(&mut self, pattern: &Pattern<'tcx>, f: &mut F)
-        where F: FnMut(&mut Self, Mutability, Name, NodeId, Span, Ty<'tcx>)
+        where F: FnMut(&mut Self, Mutability, Name, BindingMode, NodeId, Span, Ty<'tcx>)
     {
         match *pattern.kind {
-            PatternKind::Binding { mutability, name, var, ty, ref subpattern, .. } => {
-                f(self, mutability, name, var, pattern.span, ty);
+            PatternKind::Binding { mutability, name, mode, var, ty, ref subpattern, .. } => {
+                f(self, mutability, name, mode, var, pattern.span, ty);
                 if let Some(subpattern) = subpattern.as_ref() {
                     self.visit_bindings(subpattern, f);
                 }
@@ -1118,15 +1118,20 @@ fn declare_binding(&mut self,
                        visibility_scope: SourceScope,
                        mutability: Mutability,
                        name: Name,
+                       mode: BindingMode,
                        var_id: NodeId,
                        var_ty: Ty<'tcx>,
                        has_guard: ArmHasGuard)
     {
-        debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, visibility_scope={:?}, \
-                source_info={:?})",
-               var_id, name, var_ty, visibility_scope, source_info);
+        debug!("declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \
+                visibility_scope={:?}, source_info={:?})",
+               var_id, name, mode, var_ty, visibility_scope, source_info);
 
         let tcx = self.hir.tcx();
+        let binding_mode = match mode {
+            BindingMode::ByValue => ty::BindingMode::BindByValue(mutability.into()),
+            BindingMode::ByRef { .. } => ty::BindingMode::BindByReference(mutability.into()),
+        };
         let local = LocalDecl::<'tcx> {
             mutability,
             ty: var_ty.clone(),
@@ -1134,7 +1139,14 @@ fn declare_binding(&mut self,
             source_info,
             visibility_scope,
             internal: false,
-            is_user_variable: true,
+            is_user_variable: Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+                binding_mode,
+                // hypothetically, `visit_bindings` could try to unzip
+                // an outermost hir::Ty as we descend, matching up
+                // idents in pat; but complex w/ unclear UI payoff.
+                // Instead, just abandon providing diagnostic info.
+                opt_ty_info: None,
+            }))),
         };
         let for_arm_body = self.local_decls.push(local.clone());
         let locals = if has_guard.0 && tcx.all_pat_vars_are_implicit_refs_within_guards() {
@@ -1145,8 +1157,9 @@ fn declare_binding(&mut self,
                 name: Some(name),
                 source_info,
                 visibility_scope,
+                // FIXME: should these secretly injected ref_for_guard's be marked as `internal`?
                 internal: false,
-                is_user_variable: true,
+                is_user_variable: None,
             });
             LocalsForNode::Three { val_for_guard, ref_for_guard, for_arm_body }
         } else {
index ca7a2daf39d2ecb9bef31b465c8710bc89aa3ec6..85671414618038781c9e4c2f81dcedf885e2112a 100644 (file)
@@ -70,11 +70,11 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
                     // HACK(eddyb) Avoid having RustCall on closures,
                     // as it adds unnecessary (and wrong) auto-tupling.
                     abi = Abi::Rust;
-                    Some((liberated_closure_env_ty(tcx, id, body_id), None))
+                    Some(ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None))
                 }
                 ty::TyGenerator(..) => {
                     let gen_ty = tcx.body_tables(body_id).node_id_to_type(fn_hir_id);
-                    Some((gen_ty, None))
+                    Some(ArgInfo(gen_ty, None, None, None))
                 }
                 _ => None,
             };
@@ -91,7 +91,23 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
                     .iter()
                     .enumerate()
                     .map(|(index, arg)| {
-                        (fn_sig.inputs()[index], Some(&*arg.pat))
+                        let owner_id = tcx.hir.body_owner(body_id);
+                        let opt_ty_info;
+                        let self_arg;
+                        if let Some(ref fn_decl) = tcx.hir.fn_decl(owner_id) {
+                            let ty_hir_id = fn_decl.inputs[index].hir_id;
+                            let ty_span = tcx.hir.span(tcx.hir.hir_to_node_id(ty_hir_id));
+                            opt_ty_info = Some(ty_span);
+                            self_arg = if index == 0 && fn_decl.has_implicit_self {
+                                Some(ImplicitSelfBinding)
+                            } else {
+                                None
+                            };
+                        } else {
+                            opt_ty_info = None;
+                            self_arg = None;
+                        }
+                        ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&*arg.pat), self_arg)
                     });
 
             let arguments = implicit_argument.into_iter().chain(explicit_arguments);
@@ -433,6 +449,13 @@ fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 ///////////////////////////////////////////////////////////////////////////
 /// the main entry point for building MIR for a function
 
+struct ImplicitSelfBinding;
+
+struct ArgInfo<'gcx>(Ty<'gcx>,
+                     Option<Span>,
+                     Option<&'gcx hir::Pat>,
+                     Option<ImplicitSelfBinding>);
+
 fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                                    fn_id: ast::NodeId,
                                    arguments: A,
@@ -442,7 +465,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                                    yield_ty: Option<Ty<'gcx>>,
                                    body: &'gcx hir::Body)
                                    -> Mir<'tcx>
-    where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
+    where A: Iterator<Item=ArgInfo<'gcx>>
 {
     let arguments: Vec<_> = arguments.collect();
 
@@ -642,13 +665,13 @@ fn finish(self,
 
     fn args_and_body(&mut self,
                      mut block: BasicBlock,
-                     arguments: &[(Ty<'gcx>, Option<&'gcx hir::Pat>)],
+                     arguments: &[ArgInfo<'gcx>],
                      argument_scope: region::Scope,
                      ast_body: &'gcx hir::Expr)
                      -> BlockAnd<()>
     {
         // Allocate locals for the function arguments
-        for &(ty, pattern) in arguments.iter() {
+        for &ArgInfo(ty, _, pattern, _) in arguments.iter() {
             // If this is a simple binding pattern, give the local a nice name for debuginfo.
             let mut name = None;
             if let Some(pat) = pattern {
@@ -668,16 +691,17 @@ fn args_and_body(&mut self,
                 visibility_scope: source_info.scope,
                 name,
                 internal: false,
-                is_user_variable: false,
+                is_user_variable: None,
             });
         }
 
         let mut scope = None;
         // Bind the argument patterns
-        for (index, &(ty, pattern)) in arguments.iter().enumerate() {
+        for (index, arg_info) in arguments.iter().enumerate() {
             // Function arguments always get the first Local indices after the return place
             let local = Local::new(index + 1);
             let place = Place::Local(local);
+            let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
 
             if let Some(pattern) = pattern {
                 let pattern = self.hir.pattern_from_hir(pattern);
@@ -686,6 +710,14 @@ fn args_and_body(&mut self,
                     // Don't introduce extra copies for simple bindings
                     PatternKind::Binding { mutability, var, mode: BindingMode::ByValue, .. } => {
                         self.local_decls[local].mutability = mutability;
+                        self.local_decls[local].is_user_variable =
+                            if let Some(ImplicitSelfBinding) = self_binding {
+                                Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf))
+                            } else {
+                                let binding_mode = ty::BindingMode::BindByValue(mutability.into());
+                                Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+                                    binding_mode, opt_ty_info })))
+                            };
                         self.var_indices.insert(var, LocalsForNode::One(local));
                     }
                     _ => {
index f11d80201c28b4653351704eb6ee4216c4668e10..c703486560dcd204b3dd51000e853eedf4654365 100644 (file)
@@ -144,7 +144,7 @@ fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl {
         source_info,
         visibility_scope: source_info.scope,
         internal: false,
-        is_user_variable: false
+        is_user_variable: None,
     }
 }
 
index 7ac3b7beb06d5358dc797eda9763208e3bc5d11a..a6017fafcc8d4621cbe87204329c084cbc9b76e3 100644 (file)
@@ -303,7 +303,7 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>,
         source_info,
         visibility_scope: source_info.scope,
         internal: false,
-        is_user_variable: false,
+        is_user_variable: None,
     };
     let new_ret_local = Local::new(mir.local_decls.len());
     mir.local_decls.push(new_ret);
@@ -644,7 +644,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
         source_info,
         visibility_scope: source_info.scope,
         internal: false,
-        is_user_variable: false,
+        is_user_variable: None,
     };
 
     make_generator_state_argument_indirect(tcx, def_id, &mut mir);
@@ -660,7 +660,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
         source_info,
         visibility_scope: source_info.scope,
         internal: false,
-        is_user_variable: false,
+        is_user_variable: None,
     };
 
     no_landing_pads(tcx, &mut mir);
index ae74a71dd06815de686c74a615245261056f4af9..f28e91e19b73c834dd999c6b93177923295f8248 100644 (file)
 
 static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
 
-/// Registers a custom OOM hook, replacing any that was previously registered.
+/// Registers a custom allocation error hook, replacing any that was previously registered.
 ///
-/// The OOM hook is invoked when an infallible memory allocation fails, before
+/// The allocation error hook is invoked when an infallible memory allocation fails, before
 /// the runtime aborts. The default hook prints a message to standard error,
-/// but this behavior can be customized with the [`set_oom_hook`] and
-/// [`take_oom_hook`] functions.
+/// but this behavior can be customized with the [`set_alloc_error_hook`] and
+/// [`take_alloc_error_hook`] functions.
 ///
 /// The hook is provided with a `Layout` struct which contains information
 /// about the allocation that failed.
 ///
-/// The OOM hook is a global resource.
-#[unstable(feature = "oom_hook", issue = "51245")]
-pub fn set_oom_hook(hook: fn(Layout)) {
+/// The allocation error hook is a global resource.
+#[unstable(feature = "alloc_error_hook", issue = "51245")]
+pub fn set_alloc_error_hook(hook: fn(Layout)) {
     HOOK.store(hook as *mut (), Ordering::SeqCst);
 }
 
-/// Unregisters the current OOM hook, returning it.
+/// Unregisters the current allocation error hook, returning it.
 ///
-/// *See also the function [`set_oom_hook`].*
+/// *See also the function [`set_alloc_error_hook`].*
 ///
 /// If no custom hook is registered, the default hook will be returned.
-#[unstable(feature = "oom_hook", issue = "51245")]
-pub fn take_oom_hook() -> fn(Layout) {
+#[unstable(feature = "alloc_error_hook", issue = "51245")]
+pub fn take_alloc_error_hook() -> fn(Layout) {
     let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
     if hook.is_null() {
-        default_oom_hook
+        default_alloc_error_hook
     } else {
         unsafe { mem::transmute(hook) }
     }
 }
 
-fn default_oom_hook(layout: Layout) {
+fn default_alloc_error_hook(layout: Layout) {
     dumb_print(format_args!("memory allocation of {} bytes failed", layout.size()));
 }
 
@@ -130,7 +130,7 @@ fn default_oom_hook(layout: Layout) {
 pub extern fn rust_oom(layout: Layout) -> ! {
     let hook = HOOK.load(Ordering::SeqCst);
     let hook: fn(Layout) = if hook.is_null() {
-        default_oom_hook
+        default_alloc_error_hook
     } else {
         unsafe { mem::transmute(hook) }
     };
index 55f9f4f7cfeb75d7b8a615d06d2acc0f070d00ac..d14b754ddb6614831466307656733a8ae5110b0a 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::{Global, Alloc, Layout, LayoutErr, CollectionAllocErr, oom};
+use alloc::{Global, Alloc, Layout, LayoutErr, CollectionAllocErr, handle_alloc_error};
 use hash::{BuildHasher, Hash, Hasher};
 use marker;
 use mem::{size_of, needs_drop};
@@ -699,7 +699,7 @@ unsafe fn new_uninitialized_internal(
         // point into it.
         let (layout, _) = calculate_layout::<K, V>(capacity)?;
         let buffer = Global.alloc(layout).map_err(|e| match fallibility {
-            Infallible => oom(layout),
+            Infallible => handle_alloc_error(layout),
             Fallible => e,
         })?;
 
index d5e412c3745e0e50030b289ed799126ea52d0040..ee9dafdd49eb86c897d6ed4672ff8dd0d54e5248 100644 (file)
@@ -13,6 +13,7 @@
 
 fn test() {
     let v: isize;
+    //[mir]~^ NOTE consider changing this to `mut v`
     v = 1; //[ast]~ NOTE first assignment
            //[mir]~^ NOTE first assignment
     println!("v={}", v);
index fbdd013024db56d5663960ffada8f7ca5e4d50e7..3c5f932af47cec42ed4ab5780b5ccb4ba5ab2051 100644 (file)
@@ -27,7 +27,7 @@ fn indirect_write_to_imm_box() {
     let y: Box<_> = box &mut x;
     let p = &y;
     ***p = 2; //[ast]~ ERROR cannot assign to data in a `&` reference
-              //[mir]~^ ERROR cannot assign to data in a `&` reference
+              //[mir]~^ ERROR cannot assign to `***p`
     drop(p);
 }
 
index 109fe3d1128e1990b186e36158e679b864db127d..f4f40e0407fded4e6443df9cf009877b248c0730 100644 (file)
@@ -70,6 +70,6 @@ fn main() {
     };
     s[2] = 20;
     //[ast]~^ ERROR cannot assign to immutable indexed content
-    //[mir]~^^ ERROR cannot assign to immutable item
+    //[mir]~^^ ERROR cannot assign to data in a `&` reference
     drop(rs);
 }
index ecddb4c101fdf7f89d26008f9ff4768dc2e513fd..61e19ffc0d293b7db19a27131db79728eddaecb5 100644 (file)
@@ -13,6 +13,7 @@
 
 fn test_drop_replace() {
     let b: Box<isize>;
+    //[mir]~^ NOTE consider changing this to `mut b`
     b = Box::new(1);    //[ast]~ NOTE first assignment
                         //[mir]~^ NOTE first assignment
     b = Box::new(2);    //[ast]~ ERROR cannot assign twice to immutable variable
@@ -24,6 +25,7 @@ fn test_drop_replace() {
 fn test_call() {
     let b = Box::new(1);    //[ast]~ NOTE first assignment
                             //[mir]~^ NOTE first assignment
+                            //[mir]~| NOTE consider changing this to `mut b`
     b = Box::new(2);        //[ast]~ ERROR cannot assign twice to immutable variable
                             //[mir]~^ ERROR cannot assign twice to immutable variable `b`
                             //[ast]~| NOTE cannot assign twice to immutable
@@ -31,7 +33,7 @@ fn test_call() {
 }
 
 fn test_args(b: Box<i32>) {  //[ast]~ NOTE first assignment
-                                //[mir]~^ NOTE argument not declared as `mut`
+                                //[mir]~^ NOTE consider changing this to `mut b`
     b = Box::new(2);            //[ast]~ ERROR cannot assign twice to immutable variable
                                 //[mir]~^ ERROR cannot assign to immutable argument `b`
                                 //[ast]~| NOTE cannot assign twice to immutable
index f28906ddb955fccd02f1d4e21a1cf9be1a1ffe4c..7bc3680ca772343b51bafa75f343847445487c0d 100644 (file)
@@ -13,6 +13,7 @@
 
 fn test() {
     let v: isize;
+    //[mir]~^ NOTE consider changing this to `mut v`
     loop {
         v = 1; //[ast]~ ERROR cannot assign twice to immutable variable
                //[mir]~^ ERROR cannot assign twice to immutable variable `v`
index 594cc0761214aa2fbd2892af7ae34d0c100fe1e8..7812cdd8684f6c773599909581afcb7db2c2498e 100644 (file)
@@ -13,6 +13,7 @@
 
 fn test() {
     let v: isize;
+    //[mir]~^ NOTE consider changing this to `mut v`
     v = 2;  //[ast]~ NOTE first assignment
             //[mir]~^ NOTE first assignment
     v += 1; //[ast]~ ERROR cannot assign twice to immutable variable
index b4fb33ca15e2660d77c0ef5a937e2ebed5311806..bb61a9037d906c9b80939e26350de5ca426c5b64 100644 (file)
@@ -14,6 +14,7 @@
 fn test() {
     let b = Box::new(1); //[ast]~ NOTE first assignment
                          //[mir]~^ NOTE first assignment
+                         //[mir]~| NOTE consider changing this to `mut b`
     drop(b);
     b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable
                      //[mir]~^ ERROR cannot assign twice to immutable variable `b`
index 7204b5d5f2e169e742f1c5d33c499418a71eed47..672e9fab83743b8bf7b668fa17029850878ace20 100644 (file)
@@ -14,6 +14,7 @@
 fn test() {
     let v: isize = 1; //[ast]~ NOTE first assignment
                       //[mir]~^ NOTE first assignment
+                      //[mir]~| NOTE consider changing this to `mut v`
     v.clone();
     v = 2; //[ast]~ ERROR cannot assign twice to immutable variable
            //[mir]~^ ERROR cannot assign twice to immutable variable `v`
index 0dbd61413e053d9ebd23976eddff7f2665c55857..f20719ec7fab7193a0699445284a9366132b3a39 100644 (file)
@@ -23,6 +23,6 @@ fn main() {
     call(|| {
         counter += 1;
         //[ast]~^ ERROR cannot assign to data in a captured outer variable in an `Fn` closure
-        //[mir]~^^ ERROR cannot assign to immutable item `counter`
+        //[mir]~^^ ERROR cannot assign to `counter`
     });
 }
index f1fdbfc702ddf6dfcb40f4c642dd579488472ba5..f15b013c07ba497a02278a7fa3c1d55788841732 100644 (file)
 
 #![feature(allocator_api, nonnull)]
 
-use std::alloc::{Alloc, Global, Layout, oom};
+use std::alloc::{Alloc, Global, Layout, handle_alloc_error};
 
 fn main() {
     unsafe {
-        let ptr = Global.alloc_one::<i32>().unwrap_or_else(|_| oom(Layout::new::<i32>()));
+        let ptr = Global.alloc_one::<i32>().unwrap_or_else(|_| {
+            handle_alloc_error(Layout::new::<i32>())
+        });
         *ptr.as_ptr() = 4;
         assert_eq!(*ptr.as_ptr(), 4);
         Global.dealloc_one(ptr);
index 7152e721eac9e63642ef45ffae13e4571b79506f..3b4b458bb0477508081a4d36cb0f1e157812ef81 100644 (file)
@@ -15,7 +15,7 @@
 
 #![feature(heap_api, allocator_api)]
 
-use std::alloc::{Global, Alloc, Layout, oom};
+use std::alloc::{Global, Alloc, Layout, handle_alloc_error};
 use std::ptr::{self, NonNull};
 
 fn main() {
@@ -50,7 +50,7 @@ unsafe fn allocate(layout: Layout) -> *mut u8 {
             println!("allocate({:?})", layout);
         }
 
-        let ret = Global.alloc(layout).unwrap_or_else(|_| oom(layout));
+        let ret = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
 
         if PRINT {
             println!("allocate({:?}) = {:?}", layout, ret);
@@ -73,7 +73,9 @@ unsafe fn reallocate(ptr: *mut u8, old: Layout, new: Layout) -> *mut u8 {
         }
 
         let ret = Global.realloc(NonNull::new_unchecked(ptr), old, new.size())
-            .unwrap_or_else(|_| oom(Layout::from_size_align_unchecked(new.size(), old.align())));
+            .unwrap_or_else(|_| handle_alloc_error(
+                Layout::from_size_align_unchecked(new.size(), old.align())
+            ));
 
         if PRINT {
             println!("reallocate({:?}, old={:?}, new={:?}) = {:?}",
index 745a19dec4d785fc11c7839f23b0950d660b289a..b58e837f3bdcf27359f8d21a336b0cde0119cafd 100644 (file)
@@ -12,7 +12,7 @@
 
 #![feature(allocator_api)]
 
-use std::alloc::{Alloc, Global, Layout, oom};
+use std::alloc::{Alloc, Global, Layout, handle_alloc_error};
 use std::ptr::NonNull;
 
 struct arena(());
@@ -33,7 +33,7 @@ struct Ccx {
 fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> {
     unsafe {
         let layout = Layout::new::<Bcx>();
-        let ptr = Global.alloc(layout).unwrap_or_else(|_| oom(layout));
+        let ptr = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
         &*(ptr.as_ptr() as *const _)
     }
 }
diff --git a/src/test/ui/asm-out-assign-imm.nll.stderr b/src/test/ui/asm-out-assign-imm.nll.stderr
new file mode 100644 (file)
index 0000000..fbd58cd
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/asm-out-assign-imm.rs:33:9
+   |
+LL |     let x: isize;
+   |         - consider changing this to `mut x`
+LL |     x = 1;
+   |     ----- first assignment to `x`
+...
+LL |         asm!("mov $1, $0" : "=r"(x) : "r"(5));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
index deb2e7ed4a33dfaeee88d3d1ed071128ce3fb7cc..592f666eff8f3955b2f8af28f90bac2df13117f4 100644 (file)
@@ -17,6 +17,9 @@ LL | |     x;  //~ value moved here
 error[E0596]: cannot borrow immutable item `y` as mutable
   --> $DIR/augmented-assignments.rs:30:5
    |
+LL |     let y = Int(2);
+   |         - help: consider changing this to be mutable: `mut y`
+LL |     //~^ consider changing this to `mut y`
 LL |     y   //~ error: cannot borrow immutable local variable `y` as mutable
    |     ^ cannot borrow as mutable
 
index b7506849b817d52dead7277f0e3be46211118ac4..1cf68795bf07f5e3dc4101d9162eebdb259068ed 100644 (file)
@@ -10,7 +10,7 @@ error[E0384]: cannot assign to immutable argument `_x` (Mir)
   --> $DIR/immutable-arg.rs:14:5
    |
 LL | fn foo(_x: u32) {
-   |        -- argument not declared as `mut`
+   |        -- consider changing this to `mut _x`
 LL |     _x = 4;
    |     ^^^^^^ cannot assign to immutable argument
 
index 1aec71fee347b397665b502ffb44f1d9d6238eb6..a008a408d97112116774c66e4b3234f24c7896d1 100644 (file)
@@ -14,13 +14,13 @@ error[E0594]: cannot assign to immutable item `x`
   --> $DIR/issue-45983.rs:17:18
    |
 LL |     give_any(|y| x = Some(y));
-   |                  ^^^^^^^^^^^ cannot mutate
-   |
-   = note: the value which is causing this path not to be mutable is...: `x`
+   |                  ^^^^^^^^^^^ 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
 
index f8b84bce04ecfdb11df2fc069aa0cef7b0f195af..0674c8230165aa20713708cf551c43ebb2d5068f 100644 (file)
@@ -1,6 +1,8 @@
 error[E0596]: cannot borrow immutable item `b` as mutable
   --> $DIR/mut-borrow-of-mut-ref.rs:18:7
    |
+LL | fn f(b: &mut i32) {
+   |      - help: consider changing this to be mutable: `mut b`
 LL |     g(&mut b) //~ ERROR cannot borrow
    |       ^^^^^^ cannot borrow as mutable
 
index 4526616e48899dce909577308d39b7bcc4edd443..da0b201f5d4e160b6b6d191a8c0dce5adc6ab7d2 100644 (file)
@@ -1,6 +1,9 @@
 error[E0596]: cannot borrow immutable item `x` as mutable
   --> $DIR/huge_multispan_highlight.rs:100:13
    |
+LL |     let x = "foo";
+   |         - help: consider changing this to be mutable: `mut x`
+...
 LL |     let y = &mut x; //~ ERROR cannot borrow
    |             ^^^^^^ cannot borrow as mutable
 
index 2d5a31f0586b192e65ab99ab2a4fdd4766279f42..10dcf7d0e657a38d177b763486190b1d1da6f925 100644 (file)
@@ -2,7 +2,9 @@ error[E0384]: cannot assign twice to immutable variable `x`
   --> $DIR/command-line-diagnostics.rs:16:5
    |
 LL |     let x = 42;
-   |             -- first assignment to `x`
+   |         -   -- first assignment to `x`
+   |         |
+   |         consider changing this to `mut x`
 LL |     x = 43;
    |     ^^^^^^ cannot assign twice to immutable variable
 
index 6b63f64c699e283905e10dece0fe3f6a5fdb309e..21c5e3608c00b5dd73fbffac57fa5f504731c930 100644 (file)
@@ -7,6 +7,8 @@ LL |         (&mut self).bar(); //~ ERROR cannot borrow
 error[E0596]: cannot borrow immutable item `self` as mutable
   --> $DIR/issue-31424.rs:23:9
    |
+LL |     fn bar(self: &mut Self) {
+   |            ---- help: consider changing this to be mutable: `mut self`
 LL |         (&mut self).bar(); //~ ERROR cannot borrow
    |         ^^^^^^^^^^^ cannot borrow as mutable
 
index 81f858f6bfcb007096c57418768bc0445c02971f..8dedb6ec4db80a1eed930a3e5168805c7546cef8 100644 (file)
@@ -2,7 +2,10 @@ error[E0596]: cannot borrow immutable item `self` as mutable
   --> $DIR/issue-34126.rs:16:18
    |
 LL |         self.run(&mut self); //~ ERROR cannot borrow
-   |                  ^^^^^^^^^ cannot borrow as mutable
+   |                  ^^^^^^^^^
+   |                  |
+   |                  cannot borrow as mutable
+   |                  try removing `&mut` here
 
 error[E0502]: cannot borrow `self` as mutable because it is also borrowed as immutable
   --> $DIR/issue-34126.rs:16:18
index 258e1bb1ad7da4dd18e44d06b5dcbb993f86e885..d2271e8e7de76b5ee9cf526f745edb54d1e56aeb 100644 (file)
@@ -2,7 +2,10 @@ error[E0596]: cannot borrow immutable item `key` as mutable
   --> $DIR/issue-34337.rs:16:9
    |
 LL |     get(&mut key); //~ ERROR cannot borrow
-   |         ^^^^^^^^ cannot borrow as mutable
+   |         ^^^^^^^^
+   |         |
+   |         cannot borrow as mutable
+   |         try removing `&mut` here
 
 error: aborting due to previous error
 
index 40b640b63cf32deee09ec1d4e3e8ac8b6f899fd9..0c1dcb29d4d2c2067f795325946bc69e76d45ed7 100644 (file)
@@ -1,16 +1,18 @@
 error[E0596]: cannot borrow immutable item `f.v` as mutable
   --> $DIR/issue-35937.rs:17:5
    |
+LL |     let f = Foo { v: Vec::new() };
+   |         - help: consider changing this to be mutable: `mut f`
 LL |     f.v.push("cat".to_string()); //~ ERROR cannot borrow
    |     ^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `f`
 
 error[E0384]: cannot assign twice to immutable variable `s.x`
   --> $DIR/issue-35937.rs:26:5
    |
 LL |     let s = S { x: 42 };
-   |             ----------- first assignment to `s.x`
+   |         -   ----------- first assignment to `s.x`
+   |         |
+   |         consider changing this to `mut s`
 LL |     s.x += 1; //~ ERROR cannot assign
    |     ^^^^^^^^ cannot assign twice to immutable variable
 
@@ -18,7 +20,10 @@ error[E0384]: cannot assign twice to immutable variable `s.x`
   --> $DIR/issue-35937.rs:30:5
    |
 LL | fn bar(s: S) {
-   |        - first assignment to `s.x`
+   |        -
+   |        |
+   |        first assignment to `s.x`
+   |        consider changing this to `mut s`
 LL |     s.x += 1; //~ ERROR cannot assign
    |     ^^^^^^^^ cannot assign twice to immutable variable
 
index 29c7192a98bc6513915628179e5aa106e5ccb34b..e51a1baad25f26685fdfc7a43477e936986a67de 100644 (file)
@@ -2,7 +2,10 @@ error[E0596]: cannot borrow immutable item `x` as mutable
   --> $DIR/issue-37139.rs:22:18
    |
 LL |             test(&mut x); //~ ERROR cannot borrow immutable
-   |                  ^^^^^^ cannot borrow as mutable
+   |                  ^^^^^^
+   |                  |
+   |                  cannot borrow as mutable
+   |                  try removing `&mut` here
 
 error: aborting due to previous error
 
index 8e4426779517c74782bc6e05eb38901e3138f18b..76b8c8ebf602940058e6828efbb1b1a2836de961 100644 (file)
@@ -1,10 +1,10 @@
 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<'_>`
 LL |         self.s.push('x'); //~ ERROR cannot borrow data mutably
-   |         ^^^^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `*self`
+   |         ^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error: aborting due to previous error
 
index 6808222cc3241356a46583ebf4b159b772cd84d7..c875957623b62841a675fbd11ce9e9340380c49f 100644 (file)
@@ -1,10 +1,10 @@
 error[E0596]: cannot borrow immutable item `*f.s` as mutable
   --> $DIR/issue-38147-4.rs:16:5
    |
+LL | fn f(x: usize, f: &Foo) {
+   |                   ---- help: consider changing this to be a mutable reference: `&mut Foo<'_>`
 LL |     f.s.push('x'); //~ ERROR cannot borrow data mutably
-   |     ^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `*f`
+   |     ^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error: aborting due to previous error
 
index f5f5b675e7727b53d90096a75084975ed066da0b..02c1debca69b24fa515978b7e4c757612eba2fc1 100644 (file)
 error[E0596]: cannot borrow immutable item `z.x` as mutable
   --> $DIR/issue-39544.rs:21:13
    |
+LL |     let z = Z { x: X::Y };
+   |         - help: consider changing this to be mutable: `mut z`
 LL |     let _ = &mut z.x; //~ ERROR cannot borrow
    |             ^^^^^^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `z`
 
 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`
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
-   |                 ^^^^^^^^^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `*self`
+   |                 ^^^^^^^^^^^ `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
   --> $DIR/issue-39544.rs:30:17
    |
+LL |     fn foo1(&self, other: &Z) {
+   |             ----- help: consider changing this to be a mutable reference: `&mut Z`
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
-   |                 ^^^^^^^^^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `*self`
+   |                 ^^^^^^^^^^^ `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
   --> $DIR/issue-39544.rs:31:17
    |
+LL |     fn foo1(&self, other: &Z) {
+   |                           -- help: consider changing this to be a mutable reference: `&mut Z`
+LL |         let _ = &mut self.x; //~ ERROR cannot borrow
 LL |         let _ = &mut other.x; //~ ERROR cannot borrow
-   |                 ^^^^^^^^^^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `*other`
+   |                 ^^^^^^^^^^^^ `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
   --> $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`
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
-   |                 ^^^^^^^^^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `*self`
+   |                 ^^^^^^^^^^^ `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
   --> $DIR/issue-39544.rs:36:17
    |
+LL |     fn foo2<'a>(&'a self, other: &Z) {
+   |                                  -- help: consider changing this to be a mutable reference: `&mut Z`
+LL |         let _ = &mut self.x; //~ ERROR cannot borrow
 LL |         let _ = &mut other.x; //~ ERROR cannot borrow
-   |                 ^^^^^^^^^^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `*other`
+   |                 ^^^^^^^^^^^^ `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
   --> $DIR/issue-39544.rs:40:17
    |
+LL |     fn foo3<'a>(self: &'a Self, other: &Z) {
+   |                       -------- help: consider changing this to be a mutable reference: `&mut Z`
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
-   |                 ^^^^^^^^^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `*self`
+   |                 ^^^^^^^^^^^ `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
   --> $DIR/issue-39544.rs:41:17
    |
+LL |     fn foo3<'a>(self: &'a Self, other: &Z) {
+   |                                        -- help: consider changing this to be a mutable reference: `&mut Z`
+LL |         let _ = &mut self.x; //~ ERROR cannot borrow
 LL |         let _ = &mut other.x; //~ ERROR cannot borrow
-   |                 ^^^^^^^^^^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `*other`
+   |                 ^^^^^^^^^^^^ `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
   --> $DIR/issue-39544.rs:45:17
    |
+LL |     fn foo4(other: &Z) {
+   |                    -- help: consider changing this to be a mutable reference: `&mut Z`
 LL |         let _ = &mut other.x; //~ ERROR cannot borrow
-   |                 ^^^^^^^^^^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `*other`
+   |                 ^^^^^^^^^^^^ `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
   --> $DIR/issue-39544.rs:51:13
    |
+LL | pub fn with_arg(z: Z, w: &Z) {
+   |                 - help: consider changing this to be mutable: `mut z`
 LL |     let _ = &mut z.x; //~ ERROR cannot borrow
    |             ^^^^^^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `z`
 
 error[E0596]: cannot borrow immutable item `w.x` as mutable
   --> $DIR/issue-39544.rs:52:13
    |
+LL | pub fn with_arg(z: Z, w: &Z) {
+   |                          -- help: consider changing this to be a mutable reference: `&mut Z`
+LL |     let _ = &mut z.x; //~ ERROR cannot borrow
 LL |     let _ = &mut w.x; //~ ERROR cannot borrow
-   |             ^^^^^^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `*w`
+   |             ^^^^^^^^ `w` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0594]: cannot assign to immutable item `*x.0`
+error[E0594]: cannot assign to `*x.0` which is behind a `&` reference
   --> $DIR/issue-39544.rs:58:5
    |
 LL |     *x.0 = 1;
-   |     ^^^^^^^^ cannot mutate
+   |     ^^^^^^^^ cannot assign
 
 error: aborting due to 12 previous errors
 
index 489e1c39c46b9504f9bf00fe4d8a69662af1f81d..1fd75de81284fd363b62fa149f616dd7894aeb96 100644 (file)
@@ -1,8 +1,10 @@
 error[E0596]: cannot borrow immutable item `*buf` as mutable
   --> $DIR/issue-40823.rs:13:5
    |
+LL |     let mut buf = &[1, 2, 3, 4];
+   |                   ------------- help: consider changing this to be a mutable reference: `&mut [1, 2, 3, 4]`
 LL |     buf.iter_mut(); //~ ERROR cannot borrow immutable borrowed content
-   |     ^^^ cannot borrow as mutable
+   |     ^^^ `buf` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error: aborting due to previous error
 
index 0525e16239d2cb606f8fa29442cb7dc30895bcd1..66e46dfe29d70d7cfc6b2f4dafdca49243e370dd 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference
   --> $DIR/E0389.rs:18:5
    |
 LL |     let fancy_ref = &(&mut fancy);
index 8045993747934a09c8bad37c719df935f877fa3b..be10b1d517bdc6c16af40bb31bef21b15a9cc0f8 100644 (file)
@@ -1,10 +1,10 @@
 error[E0596]: cannot borrow immutable item `*x` as mutable
   --> $DIR/issue-36400.rs:15:7
    |
+LL |     let x = Box::new(3);
+   |         - help: consider changing this to be mutable: `mut x`
 LL |     f(&mut *x); //~ ERROR cannot borrow immutable
    |       ^^^^^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `x`
 
 error: aborting due to previous error
 
index 9d6d68f518d72997542dbcb959647cb68c1cabf8..93f2837c0fc11ce2b838da0757d829d87805cd54 100644 (file)
@@ -18,7 +18,7 @@ error[E0384]: cannot assign to immutable argument `y`
   --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:5
    |
 LL | fn foo(mut x: Ref, y: &u32) {
-   |                    - argument not declared as `mut`
+   |                    - consider changing this to `mut y`
 LL |     y = x.b; //~ ERROR lifetime mismatch
    |     ^^^^^^^ cannot assign to immutable argument
 
index f58f33c9a9adbced2b9eca788f152104b8153b91..01e26980323949cac18c34806e96e9453f4cc79a 100644 (file)
@@ -15,6 +15,8 @@ LL |   y.push(z); //~ ERROR lifetime mismatch
 error[E0596]: cannot borrow immutable item `y` 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) {
+   |                        - help: consider changing this to be mutable: `mut y`
 LL |   y.push(z); //~ ERROR lifetime mismatch
    |   ^ cannot borrow as mutable
 
index 4bfb4ac2833c8c77c36b7b516530198bc8a80c68..a61d49fc953dbd9eb2ba896d5eddccca5c8179b4 100644 (file)
@@ -15,6 +15,8 @@ LL |   y.push(z); //~ ERROR lifetime mismatch
 error[E0596]: cannot borrow immutable item `y` 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) {
+   |                              - help: consider changing this to be mutable: `mut y`
 LL |   y.push(z); //~ ERROR lifetime mismatch
    |   ^ cannot borrow as mutable
 
index 43743118966596dde663f6af9dac9e9ae1a63ef5..0620235371a3928126d3037102188b5002ed61b6 100644 (file)
@@ -32,6 +32,9 @@ LL |             x = 2;      //~ ERROR (Ast) [E0384]
 error[E0384]: cannot assign twice to immutable variable `x` (Mir)
   --> $DIR/liveness-assign-imm-local-notes.rs:23:9
    |
+LL |     let x;
+   |         - consider changing this to `mut x`
+...
 LL |         x = 2;
    |         ----- first assignment to `x`
 LL |         x = 3;      //~ ERROR (Ast) [E0384]
@@ -40,6 +43,9 @@ LL |         x = 3;      //~ ERROR (Ast) [E0384]
 error[E0384]: cannot assign twice to immutable variable `x` (Mir)
   --> $DIR/liveness-assign-imm-local-notes.rs:35:13
    |
+LL |         let x;
+   |             - consider changing this to `mut x`
+...
 LL |             x = 2;
    |             ----- first assignment to `x`
 LL |             x = 3;      //~ ERROR (Ast) [E0384]
@@ -48,12 +54,18 @@ LL |             x = 3;      //~ ERROR (Ast) [E0384]
 error[E0384]: cannot assign twice to immutable variable `x` (Mir)
   --> $DIR/liveness-assign-imm-local-notes.rs:45:13
    |
+LL |     let x;
+   |         - consider changing this to `mut x`
+...
 LL |             x = 1;      //~ ERROR (Ast) [E0384]
    |             ^^^^^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `x` (Mir)
   --> $DIR/liveness-assign-imm-local-notes.rs:48:13
    |
+LL |     let x;
+   |         - consider changing this to `mut x`
+...
 LL |             x = 1;      //~ ERROR (Ast) [E0384]
    |             ----- first assignment to `x`
 ...
index a12baab415907892419e271e5a1f9f3a6ac652cc..213eddee720d3e081949e761f6762e0d9955b00a 100644 (file)
@@ -1,6 +1,8 @@
 error[E0596]: cannot borrow immutable item `foo` as mutable
   --> $DIR/span-covering-argument-1.rs:15:14
    |
+LL |             let $s = 0;
+   |                 -- help: consider changing this to be mutable: `mut foo`
 LL |             *&mut $s = 0;
    |              ^^^^^^^ cannot borrow as mutable
 ...
index f3952c49a2a36fecd13ff84996782ed83cff5d39..96e9f1554144788a6ecbaf1ccf0a15a6f85fea83 100644 (file)
@@ -1,4 +1,4 @@
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference
   --> $DIR/issue-47388.rs:18:5
    |
 LL |     let fancy_ref = &(&mut fancy);
diff --git a/src/test/ui/reassign-ref-mut.rs b/src/test/ui/reassign-ref-mut.rs
new file mode 100644 (file)
index 0000000..c045720
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2017 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.
+
+// Tests how we behave when the user attempts to mutate an immutable
+// binding that was introduced by either `ref` or `ref mut`
+// patterns.
+//
+// Such bindings cannot be made mutable via the mere addition of the
+// `mut` keyword, and thus we want to check that the compiler does not
+// suggest doing so.
+
+fn main() {
+    let (mut one_two, mut three_four) = ((1, 2), (3, 4));
+    let &mut (ref a, ref mut b) = &mut one_two;
+    a = &three_four.0;
+    //~^ ERROR cannot assign twice to immutable variable `a` [E0384]
+    b = &mut three_four.1;
+    //~^ ERROR cannot assign twice to immutable variable `b` [E0384]
+}
diff --git a/src/test/ui/reassign-ref-mut.stderr b/src/test/ui/reassign-ref-mut.stderr
new file mode 100644 (file)
index 0000000..bf627dd
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0384]: cannot assign twice to immutable variable `a`
+  --> $DIR/reassign-ref-mut.rs:22:5
+   |
+LL |     let &mut (ref a, ref mut b) = &mut one_two;
+   |               ----- first assignment to `a`
+LL |     a = &three_four.0;
+   |     ^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `b`
+  --> $DIR/reassign-ref-mut.rs:24:5
+   |
+LL |     let &mut (ref a, ref mut b) = &mut one_two;
+   |                      --------- first assignment to `b`
+...
+LL |     b = &mut three_four.1;
+   |     ^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0384`.
index b97bdeea409c6310e431d7139356b1cf6f07d246..8aa7e8a417c2bea3aeb5d778768278e29720e664 100644 (file)
@@ -1,26 +1,20 @@
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `*x` which is behind a `&` reference
   --> $DIR/enum.rs:19:5
    |
-LL |     let Wrap(x) = &Wrap(3);
-   |              - help: consider changing this to be a mutable reference: `&mut`
 LL |     *x += 1; //~ ERROR cannot assign to immutable
-   |     ^^^^^^^
+   |     ^^^^^^^ cannot assign
 
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `*x` which is behind a `&` reference
   --> $DIR/enum.rs:23:9
    |
-LL |     if let Some(x) = &Some(3) {
-   |                 - help: consider changing this to be a mutable reference: `&mut`
 LL |         *x += 1; //~ ERROR cannot assign to immutable
-   |         ^^^^^^^
+   |         ^^^^^^^ cannot assign
 
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `*x` which is behind a `&` reference
   --> $DIR/enum.rs:29:9
    |
-LL |     while let Some(x) = &Some(3) {
-   |                    - help: consider changing this to be a mutable reference: `&mut`
 LL |         *x += 1; //~ ERROR cannot assign to immutable
-   |         ^^^^^^^
+   |         ^^^^^^^ cannot assign
 
 error: aborting due to 3 previous errors
 
index 3ee4dc07bb8bbb05bb993fcdfe2ec3bcd1341aa4..4e00dec761621ac58d317944e99a1275c270ea28 100644 (file)
@@ -1,26 +1,20 @@
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `*n` which is behind a `&` reference
   --> $DIR/explicit-mut.rs:17:13
    |
-LL |         Some(n) => {
-   |              - help: consider changing this to be a mutable reference: `&mut`
 LL |             *n += 1; //~ ERROR cannot assign to immutable
-   |             ^^^^^^^
+   |             ^^^^^^^ cannot assign
 
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `*n` which is behind a `&` reference
   --> $DIR/explicit-mut.rs:25:13
    |
-LL |         Some(n) => {
-   |              - help: consider changing this to be a mutable reference: `&mut`
 LL |             *n += 1; //~ ERROR cannot assign to immutable
-   |             ^^^^^^^
+   |             ^^^^^^^ cannot assign
 
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `*n` which is behind a `&` reference
   --> $DIR/explicit-mut.rs:33:13
    |
-LL |         Some(n) => {
-   |              - help: consider changing this to be a mutable reference: `&mut`
 LL |             *n += 1; //~ ERROR cannot assign to immutable
-   |             ^^^^^^^
+   |             ^^^^^^^ cannot assign
 
 error: aborting due to 3 previous errors
 
index 172828b9a40f9f1bd1a2e06bbc0e56cbda21a49b..3282fbba6c5cfea76aca5fd6733a04fc25e9b21f 100644 (file)
@@ -1,50 +1,66 @@
 error[E0596]: cannot borrow immutable item `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:63:24
    |
+LL | fn deref_mut_field1(x: Own<Point>) {
+   |                     - help: consider changing this to be mutable: `mut x`
 LL |     let __isize = &mut x.y; //~ ERROR cannot borrow
    |                        ^ cannot borrow as mutable
 
 error[E0596]: cannot borrow immutable item `*x` as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:75:10
    |
+LL | fn deref_extend_mut_field1(x: &Own<Point>) -> &mut isize {
+   |                               ----------- help: consider changing this to be a mutable reference: `&mut Own<Point>`
 LL |     &mut x.y //~ ERROR cannot borrow
-   |          ^ cannot borrow as mutable
+   |          ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error[E0596]: cannot borrow immutable item `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:98:5
    |
+LL | fn assign_field1<'a>(x: Own<Point>) {
+   |                      - help: consider changing this to be mutable: `mut x`
 LL |     x.y = 3; //~ ERROR cannot borrow
    |     ^ cannot borrow as mutable
 
 error[E0596]: cannot borrow immutable item `*x` as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:102:5
    |
+LL | fn assign_field2<'a>(x: &'a Own<Point>) {
+   |                         -------------- help: consider changing this to be a mutable reference: `&mut Own<Point>`
 LL |     x.y = 3; //~ ERROR cannot borrow
-   |     ^ cannot borrow as mutable
+   |     ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error[E0596]: cannot borrow immutable item `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:119:5
    |
+LL | fn deref_mut_method1(x: Own<Point>) {
+   |                      - help: consider changing this to be mutable: `mut x`
 LL |     x.set(0, 0); //~ ERROR cannot borrow
    |     ^ cannot borrow as mutable
 
 error[E0596]: cannot borrow immutable item `*x` as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:131:5
    |
+LL | fn deref_extend_mut_method1(x: &Own<Point>) -> &mut isize {
+   |                                ----------- help: consider changing this to be a mutable reference: `&mut Own<Point>`
 LL |     x.y_mut() //~ ERROR cannot borrow
-   |     ^ cannot borrow as mutable
+   |     ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error[E0596]: cannot borrow immutable item `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:139:6
    |
+LL | fn assign_method1<'a>(x: Own<Point>) {
+   |                       - help: consider changing this to be mutable: `mut x`
 LL |     *x.y_mut() = 3; //~ ERROR cannot borrow
    |      ^ cannot borrow as mutable
 
 error[E0596]: cannot borrow immutable item `*x` as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:143:6
    |
+LL | fn assign_method2<'a>(x: &'a Own<Point>) {
+   |                          -------------- help: consider changing this to be a mutable reference: `&mut Own<Point>`
 LL |     *x.y_mut() = 3; //~ ERROR cannot borrow
-   |      ^ cannot borrow as mutable
+   |      ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error: aborting due to 8 previous errors
 
index 24abe85de76f728d604adaa91c6b2d6c6207cff4..0b1bfd8cee6730821670893decd6197ff80cf59b 100644 (file)
@@ -1,26 +1,34 @@
 error[E0596]: cannot borrow immutable item `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:39:25
    |
+LL | fn deref_mut1(x: Own<isize>) {
+   |               - help: consider changing this to be mutable: `mut x`
 LL |     let __isize = &mut *x; //~ ERROR cannot borrow
    |                         ^ cannot borrow as mutable
 
 error[E0596]: cannot borrow immutable item `*x` as mutable
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:51:11
    |
+LL | fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize {
+   |                             -------------- help: consider changing this to be a mutable reference: `&mut Own<isize>`
 LL |     &mut **x //~ ERROR cannot borrow
-   |           ^^ cannot borrow as mutable
+   |           ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error[E0596]: cannot borrow immutable item `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:59:6
    |
+LL | fn assign1<'a>(x: Own<isize>) {
+   |                - help: consider changing this to be mutable: `mut x`
 LL |     *x = 3; //~ ERROR cannot borrow
    |      ^ cannot borrow as mutable
 
 error[E0596]: cannot borrow immutable item `*x` as mutable
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:63:6
    |
+LL | fn assign2<'a>(x: &'a Own<isize>) {
+   |                   -------------- help: consider changing this to be a mutable reference: `&mut Own<isize>`
 LL |     **x = 3; //~ ERROR cannot borrow
-   |      ^^ cannot borrow as mutable
+   |      ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error: aborting due to 4 previous errors
 
index 26e9ea4dc0bc86b286cf22f096acaa46dc4bd4cc..c4bdef21de4bacdf5698a5c6ee99b7877ae1f993 100644 (file)
@@ -15,16 +15,18 @@ LL | |     }));
 error[E0596]: cannot borrow immutable item `*f` as mutable
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:35:5
    |
+LL | fn test2<F>(f: &F) where F: FnMut() {
+   |                -- help: consider changing this to be a mutable reference: `&mut F`
 LL |     (*f)();
-   |     ^^^^ cannot borrow as mutable
+   |     ^^^^ `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
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:44:5
    |
+LL | fn test4(f: &Test) {
+   |             ----- help: consider changing this to be a mutable reference: `&mut Test<'_>`
 LL |     f.f.call_mut(())
-   |     ^^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `*f`
+   |     ^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13
index 43934bf4aeec15fff36516d960922370aa5bdc62..0bc614589e3d2ef1d0361fa8db4ae37bd736b6ab 100644 (file)
@@ -1,8 +1,11 @@
 error[E0596]: cannot borrow immutable item `*x` as mutable
   --> $DIR/borrowck-call-method-from-mut-aliasable.rs:27:5
    |
+LL | fn b(x: &Foo) {
+   |         ---- help: consider changing this to be a mutable reference: `&mut Foo`
+LL |     x.f();
 LL |     x.h(); //~ ERROR cannot borrow
-   |     ^ cannot borrow as mutable
+   |     ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error: aborting due to previous error
 
index d3c6fd66599478c6de092761e2e67e959796748a..1cb2c92833c1634ab689cadce02bf38b98765fb1 100644 (file)
@@ -1,8 +1,10 @@
 error[E0596]: cannot borrow immutable item `*x` as mutable
   --> $DIR/borrowck-fn-in-const-b.rs:17:9
    |
+LL |     fn broken(x: &Vec<String>) {
+   |                  ------------ help: consider changing this to be a mutable reference: `&mut std::vec::Vec<std::string::String>`
 LL |         x.push(format!("this is broken"));
-   |         ^ cannot borrow as mutable
+   |         ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error: aborting due to previous error
 
index 9b5e084bd375134372d1863b936b27a527bcc498..cf615eed55691d3fc1db747ee184707042d3c7b8 100644 (file)
@@ -1,16 +1,20 @@
 error[E0596]: cannot borrow immutable item `*x` as mutable
   --> $DIR/borrowck-object-mutability.rs:19:5
    |
+LL | fn borrowed_receiver(x: &Foo) {
+   |                         ---- help: consider changing this to be a mutable reference: `&mut Foo`
+LL |     x.borrowed();
 LL |     x.borrowed_mut(); //~ ERROR cannot borrow
-   |     ^ cannot borrow as mutable
+   |     ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error[E0596]: cannot borrow immutable item `*x` as mutable
   --> $DIR/borrowck-object-mutability.rs:29:5
    |
+LL | fn owned_receiver(x: Box<Foo>) {
+   |                   - help: consider changing this to be mutable: `mut x`
+LL |     x.borrowed();
 LL |     x.borrowed_mut(); //~ ERROR cannot borrow
    |     ^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `x`
 
 error: aborting due to 2 previous errors
 
index 8e1cb9720e2369ac971bc8bdb30f062e1d38a169..cd19059fdae32d5121e3621de64dc28c952d7ef9 100644 (file)
@@ -1,20 +1,26 @@
 error[E0596]: cannot borrow immutable item `*a` as mutable
   --> $DIR/mut-arg-hint.rs:13:9
    |
+LL |     fn foo(mut a: &String) {
+   |                   ------- help: consider changing this to be a mutable reference: `&mut std::string::String`
 LL |         a.push_str("bar"); //~ ERROR cannot borrow immutable borrowed content
-   |         ^ cannot borrow as mutable
+   |         ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error[E0596]: cannot borrow immutable item `*a` as mutable
   --> $DIR/mut-arg-hint.rs:18:5
    |
+LL | pub fn foo<'a>(mut a: &'a String) {
+   |                       ---------- help: consider changing this to be a mutable reference: `&mut std::string::String`
 LL |     a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content
-   |     ^ cannot borrow as mutable
+   |     ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error[E0596]: cannot borrow immutable item `*a` as mutable
   --> $DIR/mut-arg-hint.rs:25:9
    |
+LL |     pub fn foo(mut a: &String) {
+   |                       ------- help: consider changing this to be a mutable reference: `&mut std::string::String`
 LL |         a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content
-   |         ^ cannot borrow as mutable
+   |         ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error: aborting due to 3 previous errors
 
index bc655114c2b471a764e8ce670620cacf369ffed3..335ccefe8a0b12096d3655d1343adf11f9232635 100644 (file)
@@ -2,7 +2,7 @@ error[E0594]: cannot assign to immutable item `y`
   --> $DIR/closure-immutable-outer-variable.rs:21:26
    |
 LL |     foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable
-   |                          ^^^^^^^^^ cannot mutate
+   |                          ^^^^^^^^^ cannot assign
 
 error: aborting due to previous error
 
index ed691843f9b26b500d44e2f1c2242318e9db4074..7ef21d3720d8833ed9180789d0907889206f7f99 100644 (file)
@@ -1,8 +1,8 @@
-error[E0594]: cannot assign to immutable item `x`
+error[E0594]: cannot assign to `x` which is behind a `&` reference
   --> $DIR/fn-closure-mutable-capture.rs:15:17
    |
 LL |     bar(move || x = 1);
-   |                 ^^^^^ cannot mutate
+   |                 ^^^^^ cannot assign
 
 error: aborting due to previous error
 
index 66547863db2fd2c8eecc7815c7e916872ef82996..1a36b0c4839b6b79a59d317c8518df502f9abe31 100644 (file)
@@ -1,18 +1,18 @@
 error[E0596]: cannot borrow immutable item `**t` as mutable
   --> $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 {
+   |                        --------------- help: consider changing this to be a mutable reference: `&mut &mut i32`
 LL |     *t //~ ERROR
-   |     ^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `*t`
+   |     ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error[E0596]: cannot borrow immutable item `**t` as mutable
   --> $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 {
+   |                             --------------- help: consider changing this to be a mutable reference: `&mut &mut i32`
 LL |     {*t} //~ ERROR
-   |      ^^ cannot borrow as mutable
-   |
-   = note: the value which is causing this path not to be mutable is...: `*t`
+   |      ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
 error: aborting due to 2 previous errors