about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSteve Klabnik <steve@steveklabnik.com>2016-05-07 15:35:18 -0400
committerSteve Klabnik <steve@steveklabnik.com>2016-05-07 15:35:18 -0400
commit0b8a3d5187a033b5d2d273f8e09133d357e2853f (patch)
treee6e8b4963213b89a74250770c0949856aca48afa
parentbe61c6d8289750f7404ac6806fdacf0f6ff8fe15 (diff)
parentf25cbe62e88a90e060ca65a4467e671c90f68e32 (diff)
downloadrust-0b8a3d5187a033b5d2d273f8e09133d357e2853f.tar.gz
rust-0b8a3d5187a033b5d2d273f8e09133d357e2853f.zip
Rollup merge of #33412 - cramertj:E0389, r=Manishearth
Add detailed error explanation for E0389

Part of #32777
-rw-r--r--src/librustc_borrowck/diagnostics.rs65
1 files changed, 64 insertions, 1 deletions
diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs
index ba8ea024c26..03fb5260c39 100644
--- a/src/librustc_borrowck/diagnostics.rs
+++ b/src/librustc_borrowck/diagnostics.rs
@@ -286,6 +286,70 @@ You can read more about cell types in the API documentation:
 https://doc.rust-lang.org/std/cell/
 "##,
 
+E0389: r##"
+An attempt was made to mutate data using a non-mutable reference. This
+commonly occurs when attempting to assign to a non-mutable reference of a
+mutable reference (`&(&mut T)`).
+
+Example of erroneous code:
+
+```compile_fail
+struct FancyNum {
+    num: u8
+}
+
+fn main() {
+    let mut fancy = FancyNum{ num: 5 };
+    let fancy_ref = &(&mut fancy);
+    fancy_ref.num = 6; // error: cannot assign to data in a `&` reference
+    println!("{}", fancy_ref.num);
+}
+```
+
+Here, `&mut fancy` is mutable, but `&(&mut fancy)` is not. Creating an
+immutable reference to a value borrows it immutably. There can be multiple
+references of type `&(&mut T)` that point to the same value, so they must be
+immutable to prevent multiple mutable references to the same value.
+
+To fix this, either remove the outer reference:
+
+```
+struct FancyNum {
+    num: u8
+}
+
+fn main() {
+    let mut fancy = FancyNum{ num: 5 };
+
+    let fancy_ref = &mut fancy;
+    // `fancy_ref` is now &mut FancyNum, rather than &(&mut FancyNum)
+
+    fancy_ref.num = 6; // No error!
+
+    println!("{}", fancy_ref.num);
+}
+```
+
+Or make the outer reference mutable:
+
+```
+struct FancyNum {
+    num: u8
+}
+
+fn main() {
+    let mut fancy = FancyNum{ num: 5 };
+
+    let fancy_ref = &mut (&mut fancy);
+    // `fancy_ref` is now &mut(&mut FancyNum), rather than &(&mut FancyNum)
+
+    fancy_ref.num = 6; // No error!
+
+    println!("{}", fancy_ref.num);
+}
+```
+"##,
+
 E0499: r##"
 A variable was borrowed as mutable more than once. Erroneous code example:
 
@@ -594,7 +658,6 @@ http://doc.rust-lang.org/stable/book/references-and-borrowing.html
 register_diagnostics! {
     E0385, // {} in an aliasable location
     E0388, // {} in a static location
-    E0389, // {} in a `&` reference
     E0500, // closure requires unique access to `..` but .. is already borrowed
     E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ...
     E0503, // cannot use `..` because it was mutably borrowed