about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2017-10-09 15:50:56 +0200
committerFelix S. Klock II <pnkfelix@pnkfx.org>2017-10-10 13:12:00 +0200
commit52cb6fc9367f3aed373d8edda7c7fa52ed9f4c25 (patch)
treee64128133c5c90e8f191fef0edb9154ddd5bab78
parent5f578dfad0dd5d43b28eff71a7e857d10c3f55fe (diff)
downloadrust-52cb6fc9367f3aed373d8edda7c7fa52ed9f4c25.tar.gz
rust-52cb6fc9367f3aed373d8edda7c7fa52ed9f4c25.zip
Moved remaining AST-borrowck diagnostic definitions to `rustc_mir` crate.
-rw-r--r--src/librustc_borrowck/diagnostics.rs469
-rw-r--r--src/librustc_borrowck/lib.rs7
-rw-r--r--src/librustc_mir/diagnostics.rs461
3 files changed, 461 insertions, 476 deletions
diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs
index 031dbcb1ebb..3fea01443be 100644
--- a/src/librustc_borrowck/diagnostics.rs
+++ b/src/librustc_borrowck/diagnostics.rs
@@ -9,472 +9,3 @@
 // except according to those terms.
 
 #![allow(non_snake_case)]
-
-register_long_diagnostics! {
-
-E0373: r##"
-This error occurs when an attempt is made to use data captured by a closure,
-when that data may no longer exist. It's most commonly seen when attempting to
-return a closure:
-
-```compile_fail,E0373
-fn foo() -> Box<Fn(u32) -> u32> {
-    let x = 0u32;
-    Box::new(|y| x + y)
-}
-```
-
-Notice that `x` is stack-allocated by `foo()`. By default, Rust captures
-closed-over data by reference. This means that once `foo()` returns, `x` no
-longer exists. An attempt to access `x` within the closure would thus be
-unsafe.
-
-Another situation where this might be encountered is when spawning threads:
-
-```compile_fail,E0373
-fn foo() {
-    let x = 0u32;
-    let y = 1u32;
-
-    let thr = std::thread::spawn(|| {
-        x + y
-    });
-}
-```
-
-Since our new thread runs in parallel, the stack frame containing `x` and `y`
-may well have disappeared by the time we try to use them. Even if we call
-`thr.join()` within foo (which blocks until `thr` has completed, ensuring the
-stack frame won't disappear), we will not succeed: the compiler cannot prove
-that this behaviour is safe, and so won't let us do it.
-
-The solution to this problem is usually to switch to using a `move` closure.
-This approach moves (or copies, where possible) data into the closure, rather
-than taking references to it. For example:
-
-```
-fn foo() -> Box<Fn(u32) -> u32> {
-    let x = 0u32;
-    Box::new(move |y| x + y)
-}
-```
-
-Now that the closure has its own copy of the data, there's no need to worry
-about safety.
-"##,
-
-E0382: r##"
-This error occurs when an attempt is made to use a variable after its contents
-have been moved elsewhere. For example:
-
-```compile_fail,E0382
-struct MyStruct { s: u32 }
-
-fn main() {
-    let mut x = MyStruct{ s: 5u32 };
-    let y = x;
-    x.s = 6;
-    println!("{}", x.s);
-}
-```
-
-Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out
-of `x` when we set `y`. This is fundamental to Rust's ownership system: outside
-of workarounds like `Rc`, a value cannot be owned by more than one variable.
-
-If we own the type, the easiest way to address this problem is to implement
-`Copy` and `Clone` on it, as shown below. This allows `y` to copy the
-information in `x`, while leaving the original version owned by `x`. Subsequent
-changes to `x` will not be reflected when accessing `y`.
-
-```
-#[derive(Copy, Clone)]
-struct MyStruct { s: u32 }
-
-fn main() {
-    let mut x = MyStruct{ s: 5u32 };
-    let y = x;
-    x.s = 6;
-    println!("{}", x.s);
-}
-```
-
-Alternatively, if we don't control the struct's definition, or mutable shared
-ownership is truly required, we can use `Rc` and `RefCell`:
-
-```
-use std::cell::RefCell;
-use std::rc::Rc;
-
-struct MyStruct { s: u32 }
-
-fn main() {
-    let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));
-    let y = x.clone();
-    x.borrow_mut().s = 6;
-    println!("{}", x.borrow().s);
-}
-```
-
-With this approach, x and y share ownership of the data via the `Rc` (reference
-count type). `RefCell` essentially performs runtime borrow checking: ensuring
-that at most one writer or multiple readers can access the data at any one time.
-
-If you wish to learn more about ownership in Rust, start with the chapter in the
-Book:
-
-https://doc.rust-lang.org/book/first-edition/ownership.html
-"##,
-
-E0383: r##"
-This error occurs when an attempt is made to partially reinitialize a
-structure that is currently uninitialized.
-
-For example, this can happen when a drop has taken place:
-
-```compile_fail,E0383
-struct Foo {
-    a: u32,
-}
-impl Drop for Foo {
-    fn drop(&mut self) { /* ... */ }
-}
-
-let mut x = Foo { a: 1 };
-drop(x); // `x` is now uninitialized
-x.a = 2; // error, partial reinitialization of uninitialized structure `t`
-```
-
-This error can be fixed by fully reinitializing the structure in question:
-
-```
-struct Foo {
-    a: u32,
-}
-impl Drop for Foo {
-    fn drop(&mut self) { /* ... */ }
-}
-
-let mut x = Foo { a: 1 };
-drop(x);
-x = Foo { a: 2 };
-```
-"##,
-
-/*E0386: r##"
-This error occurs when an attempt is made to mutate the target of a mutable
-reference stored inside an immutable container.
-
-For example, this can happen when storing a `&mut` inside an immutable `Box`:
-
-```compile_fail,E0386
-let mut x: i64 = 1;
-let y: Box<_> = Box::new(&mut x);
-**y = 2; // error, cannot assign to data in an immutable container
-```
-
-This error can be fixed by making the container mutable:
-
-```
-let mut x: i64 = 1;
-let mut y: Box<_> = Box::new(&mut x);
-**y = 2;
-```
-
-It can also be fixed by using a type with interior mutability, such as `Cell`
-or `RefCell`:
-
-```
-use std::cell::Cell;
-
-let x: i64 = 1;
-let y: Box<Cell<_>> = Box::new(Cell::new(x));
-y.set(2);
-```
-"##,*/
-
-E0387: r##"
-This error occurs when an attempt is made to mutate or mutably reference data
-that a closure has captured immutably. Examples of this error are shown below:
-
-```compile_fail,E0387
-// Accepts a function or a closure that captures its environment immutably.
-// Closures passed to foo will not be able to mutate their closed-over state.
-fn foo<F: Fn()>(f: F) { }
-
-// Attempts to mutate closed-over data. Error message reads:
-// `cannot assign to data in a captured outer variable...`
-fn mutable() {
-    let mut x = 0u32;
-    foo(|| x = 2);
-}
-
-// Attempts to take a mutable reference to closed-over data.  Error message
-// reads: `cannot borrow data mutably in a captured outer variable...`
-fn mut_addr() {
-    let mut x = 0u32;
-    foo(|| { let y = &mut x; });
-}
-```
-
-The problem here is that foo is defined as accepting a parameter of type `Fn`.
-Closures passed into foo will thus be inferred to be of type `Fn`, meaning that
-they capture their context immutably.
-
-If the definition of `foo` is under your control, the simplest solution is to
-capture the data mutably. This can be done by defining `foo` to take FnMut
-rather than Fn:
-
-```
-fn foo<F: FnMut()>(f: F) { }
-```
-
-Alternatively, we can consider using the `Cell` and `RefCell` types to achieve
-interior mutability through a shared reference. Our example's `mutable`
-function could be redefined as below:
-
-```
-use std::cell::Cell;
-
-fn foo<F: Fn()>(f: F) { }
-
-fn mutable() {
-    let x = Cell::new(0u32);
-    foo(|| x.set(2));
-}
-```
-
-You can read more about cell types in the API documentation:
-
-https://doc.rust-lang.org/std/cell/
-"##,
-
-E0388: r##"
-E0388 was removed and is no longer issued.
-"##,
-
-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,E0389
-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);
-}
-```
-"##,
-
-E0595: r##"
-Closures cannot mutate immutable captured variables.
-
-Erroneous code example:
-
-```compile_fail,E0595
-let x = 3; // error: closure cannot assign to immutable local variable `x`
-let mut c = || { x += 1 };
-```
-
-Make the variable binding mutable:
-
-```
-let mut x = 3; // ok!
-let mut c = || { x += 1 };
-```
-"##,
-
-E0596: r##"
-This error occurs because you tried to mutably borrow a non-mutable variable.
-
-Example of erroneous code:
-
-```compile_fail,E0596
-let x = 1;
-let y = &mut x; // error: cannot borrow mutably
-```
-
-In here, `x` isn't mutable, so when we try to mutably borrow it in `y`, it
-fails. To fix this error, you need to make `x` mutable:
-
-```
-let mut x = 1;
-let y = &mut x; // ok!
-```
-"##,
-
-E0597: r##"
-This error occurs because a borrow was made inside a variable which has a
-greater lifetime than the borrowed one.
-
-Example of erroneous code:
-
-```compile_fail,E0597
-struct Foo<'a> {
-    x: Option<&'a u32>,
-}
-
-let mut x = Foo { x: None };
-let y = 0;
-x.x = Some(&y); // error: `y` does not live long enough
-```
-
-In here, `x` is created before `y` and therefore has a greater lifetime. Always
-keep in mind that values in a scope are dropped in the opposite order they are
-created. So to fix the previous example, just make the `y` lifetime greater than
-the `x`'s one:
-
-```
-struct Foo<'a> {
-    x: Option<&'a u32>,
-}
-
-let y = 0;
-let mut x = Foo { x: None };
-x.x = Some(&y);
-```
-"##,
-
-E0626: r##"
-This error occurs because a borrow in a generator persists across a
-yield point.
-
-```compile_fail,E0626
-# #![feature(generators, generator_trait)]
-# use std::ops::Generator;
-let mut b = || {
-    let a = &String::new(); // <-- This borrow...
-    yield (); // ...is still in scope here, when the yield occurs.
-    println!("{}", a);
-};
-b.resume();
-```
-
-At present, it is not permitted to have a yield that occurs while a
-borrow is still in scope. To resolve this error, the borrow must
-either be "contained" to a smaller scope that does not overlap the
-yield or else eliminated in another way. So, for example, we might
-resolve the previous example by removing the borrow and just storing
-the integer by value:
-
-```
-# #![feature(generators, generator_trait)]
-# use std::ops::Generator;
-let mut b = || {
-    let a = 3;
-    yield ();
-    println!("{}", a);
-};
-b.resume();
-```
-
-This is a very simple case, of course. In more complex cases, we may
-wish to have more than one reference to the value that was borrowed --
-in those cases, something like the `Rc` or `Arc` types may be useful.
-
-This error also frequently arises with iteration:
-
-```compile_fail,E0626
-# #![feature(generators, generator_trait)]
-# use std::ops::Generator;
-let mut b = || {
-  let v = vec![1,2,3];
-  for &x in &v { // <-- borrow of `v` is still in scope...
-    yield x; // ...when this yield occurs.
-  }
-};
-b.resume();
-```
-
-Such cases can sometimes be resolved by iterating "by value" (or using
-`into_iter()`) to avoid borrowing:
-
-```
-# #![feature(generators, generator_trait)]
-# use std::ops::Generator;
-let mut b = || {
-  let v = vec![1,2,3];
-  for x in v { // <-- Take ownership of the values instead!
-    yield x; // <-- Now yield is OK.
-  }
-};
-b.resume();
-```
-
-If taking ownership is not an option, using indices can work too:
-
-```
-# #![feature(generators, generator_trait)]
-# use std::ops::Generator;
-let mut b = || {
-  let v = vec![1,2,3];
-  let len = v.len(); // (*)
-  for i in 0..len {
-    let x = v[i]; // (*)
-    yield x; // <-- Now yield is OK.
-  }
-};
-b.resume();
-
-// (*) -- Unfortunately, these temporaries are currently required.
-// See <https://github.com/rust-lang/rust/issues/43122>.
-```
-"##,
-
-}
-
-register_diagnostics! {
-//    E0385, // {} in an aliasable location
-    E0598, // lifetime of {} is too short to guarantee its contents can be...
-}
diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs
index 9bedbfed5db..94548f57249 100644
--- a/src/librustc_borrowck/lib.rs
+++ b/src/librustc_borrowck/lib.rs
@@ -16,7 +16,6 @@
 #![allow(non_camel_case_types)]
 
 #![feature(quote)]
-#![feature(rustc_diagnostic_macros)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
@@ -33,14 +32,8 @@ extern crate rustc_mir;
 pub use borrowck::check_crate;
 pub use borrowck::build_borrowck_dataflow_data_for_fn;
 
-// NB: This module needs to be declared first so diagnostics are
-// registered before they are used.
-mod diagnostics;
-
 mod borrowck;
 
 pub mod graphviz;
 
 pub use borrowck::provide;
-
-__build_diagnostic_array! { librustc_borrowck, DIAGNOSTICS }
diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs
index 645af0bff64..98c5345c69d 100644
--- a/src/librustc_mir/diagnostics.rs
+++ b/src/librustc_mir/diagnostics.rs
@@ -229,6 +229,57 @@ fn main() {
 See also https://doc.rust-lang.org/book/first-edition/unsafe.html
 "##,
 
+E0373: r##"
+This error occurs when an attempt is made to use data captured by a closure,
+when that data may no longer exist. It's most commonly seen when attempting to
+return a closure:
+
+```compile_fail,E0373
+fn foo() -> Box<Fn(u32) -> u32> {
+    let x = 0u32;
+    Box::new(|y| x + y)
+}
+```
+
+Notice that `x` is stack-allocated by `foo()`. By default, Rust captures
+closed-over data by reference. This means that once `foo()` returns, `x` no
+longer exists. An attempt to access `x` within the closure would thus be
+unsafe.
+
+Another situation where this might be encountered is when spawning threads:
+
+```compile_fail,E0373
+fn foo() {
+    let x = 0u32;
+    let y = 1u32;
+
+    let thr = std::thread::spawn(|| {
+        x + y
+    });
+}
+```
+
+Since our new thread runs in parallel, the stack frame containing `x` and `y`
+may well have disappeared by the time we try to use them. Even if we call
+`thr.join()` within foo (which blocks until `thr` has completed, ensuring the
+stack frame won't disappear), we will not succeed: the compiler cannot prove
+that this behaviour is safe, and so won't let us do it.
+
+The solution to this problem is usually to switch to using a `move` closure.
+This approach moves (or copies, where possible) data into the closure, rather
+than taking references to it. For example:
+
+```
+fn foo() -> Box<Fn(u32) -> u32> {
+    let x = 0u32;
+    Box::new(move |y| x + y)
+}
+```
+
+Now that the closure has its own copy of the data, there's no need to worry
+about safety.
+"##,
+
 E0381: r##"
 It is not allowed to use or capture an uninitialized variable. For example:
 
@@ -250,6 +301,104 @@ fn main() {
 ```
 "##,
 
+E0382: r##"
+This error occurs when an attempt is made to use a variable after its contents
+have been moved elsewhere. For example:
+
+```compile_fail,E0382
+struct MyStruct { s: u32 }
+
+fn main() {
+    let mut x = MyStruct{ s: 5u32 };
+    let y = x;
+    x.s = 6;
+    println!("{}", x.s);
+}
+```
+
+Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out
+of `x` when we set `y`. This is fundamental to Rust's ownership system: outside
+of workarounds like `Rc`, a value cannot be owned by more than one variable.
+
+If we own the type, the easiest way to address this problem is to implement
+`Copy` and `Clone` on it, as shown below. This allows `y` to copy the
+information in `x`, while leaving the original version owned by `x`. Subsequent
+changes to `x` will not be reflected when accessing `y`.
+
+```
+#[derive(Copy, Clone)]
+struct MyStruct { s: u32 }
+
+fn main() {
+    let mut x = MyStruct{ s: 5u32 };
+    let y = x;
+    x.s = 6;
+    println!("{}", x.s);
+}
+```
+
+Alternatively, if we don't control the struct's definition, or mutable shared
+ownership is truly required, we can use `Rc` and `RefCell`:
+
+```
+use std::cell::RefCell;
+use std::rc::Rc;
+
+struct MyStruct { s: u32 }
+
+fn main() {
+    let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));
+    let y = x.clone();
+    x.borrow_mut().s = 6;
+    println!("{}", x.borrow().s);
+}
+```
+
+With this approach, x and y share ownership of the data via the `Rc` (reference
+count type). `RefCell` essentially performs runtime borrow checking: ensuring
+that at most one writer or multiple readers can access the data at any one time.
+
+If you wish to learn more about ownership in Rust, start with the chapter in the
+Book:
+
+https://doc.rust-lang.org/book/first-edition/ownership.html
+"##,
+
+E0383: r##"
+This error occurs when an attempt is made to partially reinitialize a
+structure that is currently uninitialized.
+
+For example, this can happen when a drop has taken place:
+
+```compile_fail,E0383
+struct Foo {
+    a: u32,
+}
+impl Drop for Foo {
+    fn drop(&mut self) { /* ... */ }
+}
+
+let mut x = Foo { a: 1 };
+drop(x); // `x` is now uninitialized
+x.a = 2; // error, partial reinitialization of uninitialized structure `t`
+```
+
+This error can be fixed by fully reinitializing the structure in question:
+
+```
+struct Foo {
+    a: u32,
+}
+impl Drop for Foo {
+    fn drop(&mut self) { /* ... */ }
+}
+
+let mut x = Foo { a: 1 };
+drop(x);
+x = Foo { a: 2 };
+```
+"##,
+
 E0384: r##"
 This error occurs when an attempt is made to reassign an immutable variable.
 For example:
@@ -272,6 +421,161 @@ fn main() {
 ```
 "##,
 
+/*E0386: r##"
+This error occurs when an attempt is made to mutate the target of a mutable
+reference stored inside an immutable container.
+
+For example, this can happen when storing a `&mut` inside an immutable `Box`:
+
+```compile_fail,E0386
+let mut x: i64 = 1;
+let y: Box<_> = Box::new(&mut x);
+**y = 2; // error, cannot assign to data in an immutable container
+```
+
+This error can be fixed by making the container mutable:
+
+```
+let mut x: i64 = 1;
+let mut y: Box<_> = Box::new(&mut x);
+**y = 2;
+```
+
+It can also be fixed by using a type with interior mutability, such as `Cell`
+or `RefCell`:
+
+```
+use std::cell::Cell;
+
+let x: i64 = 1;
+let y: Box<Cell<_>> = Box::new(Cell::new(x));
+y.set(2);
+```
+"##,*/
+
+E0387: r##"
+This error occurs when an attempt is made to mutate or mutably reference data
+that a closure has captured immutably. Examples of this error are shown below:
+
+```compile_fail,E0387
+// Accepts a function or a closure that captures its environment immutably.
+// Closures passed to foo will not be able to mutate their closed-over state.
+fn foo<F: Fn()>(f: F) { }
+
+// Attempts to mutate closed-over data. Error message reads:
+// `cannot assign to data in a captured outer variable...`
+fn mutable() {
+    let mut x = 0u32;
+    foo(|| x = 2);
+}
+
+// Attempts to take a mutable reference to closed-over data.  Error message
+// reads: `cannot borrow data mutably in a captured outer variable...`
+fn mut_addr() {
+    let mut x = 0u32;
+    foo(|| { let y = &mut x; });
+}
+```
+
+The problem here is that foo is defined as accepting a parameter of type `Fn`.
+Closures passed into foo will thus be inferred to be of type `Fn`, meaning that
+they capture their context immutably.
+
+If the definition of `foo` is under your control, the simplest solution is to
+capture the data mutably. This can be done by defining `foo` to take FnMut
+rather than Fn:
+
+```
+fn foo<F: FnMut()>(f: F) { }
+```
+
+Alternatively, we can consider using the `Cell` and `RefCell` types to achieve
+interior mutability through a shared reference. Our example's `mutable`
+function could be redefined as below:
+
+```
+use std::cell::Cell;
+
+fn foo<F: Fn()>(f: F) { }
+
+fn mutable() {
+    let x = Cell::new(0u32);
+    foo(|| x.set(2));
+}
+```
+
+You can read more about cell types in the API documentation:
+
+https://doc.rust-lang.org/std/cell/
+"##,
+
+E0388: r##"
+E0388 was removed and is no longer issued.
+"##,
+
+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,E0389
+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);
+}
+```
+"##,
 
 E0394: r##"
 A static was referred to by value by another static.
@@ -1265,12 +1569,169 @@ fn main() {
 ```
 "##,
 
+E0595: r##"
+Closures cannot mutate immutable captured variables.
+
+Erroneous code example:
+
+```compile_fail,E0595
+let x = 3; // error: closure cannot assign to immutable local variable `x`
+let mut c = || { x += 1 };
+```
+
+Make the variable binding mutable:
+
+```
+let mut x = 3; // ok!
+let mut c = || { x += 1 };
+```
+"##,
+
+E0596: r##"
+This error occurs because you tried to mutably borrow a non-mutable variable.
+
+Example of erroneous code:
+
+```compile_fail,E0596
+let x = 1;
+let y = &mut x; // error: cannot borrow mutably
+```
+
+In here, `x` isn't mutable, so when we try to mutably borrow it in `y`, it
+fails. To fix this error, you need to make `x` mutable:
+
+```
+let mut x = 1;
+let y = &mut x; // ok!
+```
+"##,
+
+E0597: r##"
+This error occurs because a borrow was made inside a variable which has a
+greater lifetime than the borrowed one.
+
+Example of erroneous code:
+
+```compile_fail,E0597
+struct Foo<'a> {
+    x: Option<&'a u32>,
+}
+
+let mut x = Foo { x: None };
+let y = 0;
+x.x = Some(&y); // error: `y` does not live long enough
+```
+
+In here, `x` is created before `y` and therefore has a greater lifetime. Always
+keep in mind that values in a scope are dropped in the opposite order they are
+created. So to fix the previous example, just make the `y` lifetime greater than
+the `x`'s one:
+
+```
+struct Foo<'a> {
+    x: Option<&'a u32>,
+}
+
+let y = 0;
+let mut x = Foo { x: None };
+x.x = Some(&y);
+```
+"##,
+
+E0626: r##"
+This error occurs because a borrow in a generator persists across a
+yield point.
+
+```compile_fail,E0626
+# #![feature(generators, generator_trait)]
+# use std::ops::Generator;
+let mut b = || {
+    let a = &String::new(); // <-- This borrow...
+    yield (); // ...is still in scope here, when the yield occurs.
+    println!("{}", a);
+};
+b.resume();
+```
+
+At present, it is not permitted to have a yield that occurs while a
+borrow is still in scope. To resolve this error, the borrow must
+either be "contained" to a smaller scope that does not overlap the
+yield or else eliminated in another way. So, for example, we might
+resolve the previous example by removing the borrow and just storing
+the integer by value:
+
+```
+# #![feature(generators, generator_trait)]
+# use std::ops::Generator;
+let mut b = || {
+    let a = 3;
+    yield ();
+    println!("{}", a);
+};
+b.resume();
+```
+
+This is a very simple case, of course. In more complex cases, we may
+wish to have more than one reference to the value that was borrowed --
+in those cases, something like the `Rc` or `Arc` types may be useful.
+
+This error also frequently arises with iteration:
+
+```compile_fail,E0626
+# #![feature(generators, generator_trait)]
+# use std::ops::Generator;
+let mut b = || {
+  let v = vec![1,2,3];
+  for &x in &v { // <-- borrow of `v` is still in scope...
+    yield x; // ...when this yield occurs.
+  }
+};
+b.resume();
+```
+
+Such cases can sometimes be resolved by iterating "by value" (or using
+`into_iter()`) to avoid borrowing:
+
+```
+# #![feature(generators, generator_trait)]
+# use std::ops::Generator;
+let mut b = || {
+  let v = vec![1,2,3];
+  for x in v { // <-- Take ownership of the values instead!
+    yield x; // <-- Now yield is OK.
+  }
+};
+b.resume();
+```
+
+If taking ownership is not an option, using indices can work too:
+
+```
+# #![feature(generators, generator_trait)]
+# use std::ops::Generator;
+let mut b = || {
+  let v = vec![1,2,3];
+  let len = v.len(); // (*)
+  for i in 0..len {
+    let x = v[i]; // (*)
+    yield x; // <-- Now yield is OK.
+  }
+};
+b.resume();
+
+// (*) -- Unfortunately, these temporaries are currently required.
+// See <https://github.com/rust-lang/rust/issues/43122>.
+```
+"##,
+
 }
 
 register_diagnostics! {
+//    E0385, // {} in an aliasable location
     E0493, // destructors cannot be evaluated at compile-time
     E0524, // two closures require unique access to `..` at the same time
     E0526, // shuffle indices are not constant
     E0594, // cannot assign to {}
+    E0598, // lifetime of {} is too short to guarantee its contents can be...
     E0625, // thread-local statics cannot be accessed at compile-time
 }